From 3678265d7f137325e9e69ca1498bc5a6e0cf52d0 Mon Sep 17 00:00:00 2001 From: Christian Johannesen Date: Fri, 16 Oct 2026 03:14:37 +0200 Subject: [PATCH] Rebuild Fireworks simulator --- README.md | 2 +- fireworks/fireworks.asm | 625 ++++++++++++++++++++++++++++++++-------- fireworks/fireworks.prg | Bin 431 -> 1578 bytes programs.json | 4 +- 4 files changed, 509 insertions(+), 122 deletions(-) diff --git a/README.md b/README.md index a5a30c0..98840ab 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Browse and run the collection at [c64.p20.dev](https://c64.p20.dev). | SID Arpeggiator | 2026-10-16 | Music | Machine Code | `A`-`K`, `1`-`3`, `+`, `-`, Space, `Q` | Shape a looping SID arpeggio with notes, waveforms, and tempo controls. | [ASM](sid-arpeggiator/sid-arpeggiator.asm) | [Run](https://c64.p20.dev/program/sid-arpeggiator) | | Paddle Ball | 2026-10-16 | Arcade | Machine Code | `A`, `D`, Space, `Q` | Keep a fast-moving ball in play with a screen-edge paddle. | [ASM](paddle-ball/paddle-ball.asm) | [Run](https://c64.p20.dev/program/paddle-ball) | | Smooth Scroller | 2026-10-16 | Demo | Machine Code | `+`, `-`, `C`, `Q` | Send a message gliding across the screen with VIC-II fine scrolling. | [ASM](smooth-scroller/smooth-scroller.asm) | [Run](https://c64.p20.dev/program/smooth-scroller) | -| Fireworks | 2026-10-16 | Demo | Machine Code | Space, `C`, `Q` | Launch colorful PETSCII fireworks into a night sky. | [ASM](fireworks/fireworks.asm) | [Run](https://c64.p20.dev/program/fireworks) | +| Fireworks | 2026-10-16 | Demo | Machine Code | Space, `A`, `C`, `1`-`3`, `Q` | Launch colorful, noisy PETSCII fireworks above a twinkling city skyline. | [ASM](fireworks/fireworks.asm) | [Run](https://c64.p20.dev/program/fireworks) | | Jiffy Clock | 2026-10-16 | Utility | Machine Code | `R`, Space, `Q` | Turn the C64 jiffy timer into a large live digital clock. | [ASM](jiffy-clock/jiffy-clock.asm) | [Run](https://c64.p20.dev/program/jiffy-clock) | | Typing Sprint | 2026-10-16 | Word | Machine Code | `A`-`Z`, Space, `Q` | Race the clock while copying a Commodore-themed phrase. | [ASM](typing-sprint/typing-sprint.asm) | [Run](https://c64.p20.dev/program/typing-sprint) | | PETSCII Aquarium | 2026-10-16 | Simulation | Machine Code | `F`, `1`-`3`, `Q` | Watch a tiny animated aquarium and feed its roaming fish. | [ASM](petscii-aquarium/petscii-aquarium.asm) | [Run](https://c64.p20.dev/program/petscii-aquarium) | diff --git a/fireworks/fireworks.asm b/fireworks/fireworks.asm index e046024..1b1bc2f 100644 --- a/fireworks/fireworks.asm +++ b/fireworks/fireworks.asm @@ -1,4 +1,7 @@ !cpu 6510 + +; Fireworks - an animated PETSCII fireworks simulator with SID effects. +; Self-starting BASIC line: 10 SYS2061 * = $0801 !word basic_end !word 10 @@ -8,162 +11,546 @@ 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 $d418 + sta old_volume + ldx #0 +save_sid: + lda $d400,x + sta old_sid,x + inx + cpx #7 + bne save_sid lda #0 sta $d020 sta $d021 + jsr show_splash lda #147 - jsr $ffd2 - ldx #0 -print_title: - lda title,x - beq setup - jsr $ffd2 - inx - bne print_title -setup: - lda #7 - sta center_x - lda #5 - sta burst_color -main: - jsr $ffe4 + jsr CHROUT + lda #0 + sta $d020 + sta $d021 + sta show_state + sta palette + sta auto_show + sta tick + sta seed + lda #3 + sta animation_speed + lda #18 + sta auto_countdown + lda $a2 + sta last_jiffy + jsr draw_skyline + jsr draw_stars + +main_loop: + jsr GETIN + beq check_clock cmp #81 - bne not_quit + bne check_launch jmp exit -not_quit: - cmp #67 - bne launch_key - inc burst_color - lda burst_color - and #15 - sta burst_color -launch_key: +check_launch: cmp #32 - bne main - jsr launch - jmp main -launch: - lda #22 + bne check_auto + jsr launch_rocket + jmp check_clock +check_auto: + cmp #65 + bne check_color + lda auto_show + eor #1 + sta auto_show + lda #4 + sta auto_countdown + jmp check_clock +check_color: + cmp #67 + bne check_speed_one + inc palette + lda palette + and #3 + sta palette + 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 + inc seed + jsr twinkle_star + lda show_state + beq idle_frame + cmp #1 + beq update_rocket + jmp update_explosion + +idle_frame: + lda auto_show + bne auto_active + jmp main_loop +auto_active: + dec auto_countdown + beq auto_launch + jmp main_loop +auto_launch: + jsr launch_rocket + jmp main_loop + +launch_rocket: + lda show_state + bne launch_done + lda seed + clc + adc $d012 + and #31 + cmp #24 + bcc center_ready + sbc #24 +center_ready: + clc + adc #8 + sta center_x + sta rocket_x + lda #20 sta rocket_y -rise: - ldx center_x - ldy rocket_y - lda #46 - jsr plot - jsr delay - ldx center_x - ldy rocket_y + lda #1 + sta show_state + lda #2 + sta trail_length + jsr rocket_sound +launch_done: + rts + +update_rocket: + ; Erase the oldest trail cell. + lda rocket_x + sta plot_x + lda rocket_y + clc + adc #2 + cmp #20 + bcs skip_old_trail + sta plot_y lda #32 - jsr plot + ldy #0 + jsr plot_character +skip_old_trail: + ; Turn the old rocket position into a fading trail. + lda rocket_y + sta plot_y + lda #46 + ldy #7 + jsr plot_character dec rocket_y lda rocket_y - cmp #7 - bne rise - ldx #0 -burst_loop: - stx particle_index - lda burst_dx,x - clc - adc center_x - sta px - lda burst_dy,x - clc - adc rocket_y - tay - ldx px - lda #42 - jsr plot - ldx particle_index - inx - cpx #12 - bne burst_loop - jsr long_delay - ldx #0 -clear_burst: - stx particle_index - lda burst_dx,x - clc - adc center_x - sta px - lda burst_dy,x - clc - adc rocket_y - tay - ldx px + cmp #6 + bne draw_rocket + lda rocket_x + sta plot_x lda #32 - jsr plot - ldx particle_index + ldy #0 + jsr plot_character + lda #2 + sta show_state + lda #0 + sta explosion_stage + jsr explosion_sound + jsr draw_explosion + rts +draw_rocket: + sta plot_y + lda rocket_x + sta plot_x + lda #94 + ldy #1 + jsr plot_character + jsr rocket_sound + rts + +update_explosion: + jsr erase_explosion + inc explosion_stage + lda explosion_stage + cmp #5 + bcs finish_explosion + jsr explosion_sound + jsr draw_explosion + rts +finish_explosion: + lda #0 + sta show_state + lda seed + and #15 + clc + adc #8 + sta auto_countdown + jsr silence_sid + jsr draw_skyline + jsr draw_stars + rts + +draw_explosion: + lda #0 + sta particle +draw_particle_loop: + jsr select_particle_position + lda explosion_stage + tax + lda burst_chars,x + ldx particle + ldy particle_colors,x + ldx palette + beq color_ready +palette_shift_loop: + tya + clc + adc #3 + and #15 + tay + dex + bne palette_shift_loop +color_ready: + jsr plot_character + inc particle + lda particle + cmp #16 + bne draw_particle_loop + rts + +erase_explosion: + lda #0 + sta particle +erase_particle_loop: + jsr select_particle_position + lda #32 + ldy #0 + jsr plot_character + inc particle + lda particle + cmp #16 + bne erase_particle_loop + rts + +select_particle_position: + lda explosion_stage + asl + asl + asl + asl + clc + adc particle + tax + lda burst_dx,x + clc + adc center_x + sta plot_x + lda burst_dy,x + clc + adc #6 + sta plot_y + rts + +draw_stars: + ldx #0 +star_loop: + stx object_index + lda star_x,x + sta plot_x + lda star_y,x + sta plot_y + txa + and #1 + beq star_dot + lda #42 + bne paint_star +star_dot: + lda #46 +paint_star: + ldy #15 + jsr plot_character + ldx object_index + inx + cpx #18 + bne star_loop + rts + +twinkle_star: + lda seed + and #15 + tax + stx object_index + lda star_x,x + sta plot_x + lda star_y,x + sta plot_y + lda seed + and #1 + beq twinkle_dot + lda #42 + bne twinkle_paint +twinkle_dot: + lda #46 +twinkle_paint: + ldy #1 + jsr plot_character + rts + +draw_skyline: + ldx #0 +building_loop: + stx plot_x + lda building_height,x + sta height_left + lda #24 + sta plot_y +building_column: + lda #160 + ldy #11 + jsr plot_character + dec plot_y + dec height_left + bne building_column + inx + cpx #40 + bne building_loop + ; Warm windows across the skyline. + ldx #0 +window_loop: + stx object_index + lda window_x,x + sta plot_x + lda window_y,x + sta plot_y + lda #81 + ldy #7 + jsr plot_character + ldx object_index inx cpx #12 - bne clear_burst - lda center_x - clc - adc #11 - cmp #35 - bcc save_center - sbc #31 -save_center: - sta center_x + bne window_loop rts -plot: - sta char_value - lda row_lo,y + +rocket_sound: + lda rocket_y + eor #$ff + sta $d400 + lda #22 + sta $d401 + lda #$11 + sta $d404 + lda #$0f + sta $d418 + rts + +explosion_sound: + lda #0 + sta $d400 + lda #45 + sta $d401 + lda #$81 + sta $d404 + lda #$08 + sta $d405 + lda #$88 + sta $d406 + lda #$0f + sta $d418 + rts + +silence_sid: + lda #0 + sta $d404 + sta $d418 + rts + +plot_character: + sta character + sty character_color + ldy plot_y + lda screen_row_lo,y sta $fb - lda row_hi,y + lda screen_row_hi,y sta $fc - txa - tay - lda char_value - sta ($fb),y - lda $fb - clc - adc #<$d400 + lda color_row_lo,y sta $fd - lda $fc - adc #>$d400 + lda color_row_hi,y sta $fe - lda burst_color + ldy plot_x + lda character + sta ($fb),y + lda character_color sta ($fd),y rts -delay: - ldx #8 -delay_outer: + +show_splash: + lda #splash_text + sta $fc ldy #0 -delay_inner: - dey - bne delay_inner - dex - bne delay_outer +print_splash: + lda ($fb),y + beq wait_for_space + jsr CHROUT + inc $fb + bne print_splash + inc $fc + jmp print_splash +wait_for_space: + jsr GETIN + cmp #32 + bne wait_for_space rts -long_delay: - ldx #45 - bne delay_outer + exit: + jsr silence_sid + ldx #0 +restore_sid: + lda old_sid,x + sta $d400,x + inx + cpx #7 + bne restore_sid + lda old_volume + sta $d418 lda old_border sta $d020 lda old_background sta $d021 lda #147 - jsr $ffd2 + jsr CHROUT rts -title: !byte 147 -!text "FIREWORKS SPACE LAUNCH C COLOR Q QUIT" -!byte 13,0 -burst_dx: !byte 0,1,2,$ff,$fe,0,0,1,2,$ff,$fe,0 -burst_dy: !byte $fe,$ff,0,$ff,0,2,1,1,2,1,2,$ff -row_lo: !for i,0,24 { !byte <($0400+i*40) } -row_hi: !for i,0,24 { !byte >($0400+i*40) } +splash_text: +!byte 147,13,13,13 +!byte 154 +!text " FIREWORKS" +!byte 13,13 +!byte 5 +!text " A PETSCII SKY FULL OF COLOR AND SOUND" +!byte 13,13,13 +!byte 153 +!text " CONTROLS" +!byte 13,13 +!text " " +!byte 158 +!text "SPACE" +!byte 5 +!text " LAUNCH " +!byte 158 +!text "A" +!byte 5 +!text " AUTO " +!byte 158 +!text "C" +!byte 5 +!text " COLOR" +!byte 13 +!text " " +!byte 158 +!text "1-3" +!byte 5 +!text " SPEED " +!byte 158 +!text "Q" +!byte 5 +!text " QUIT" +!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 + +; Five expansion stages, sixteen points per stage. Signed offsets are stored +; as bytes; normal 6502 wrapping performs the addition around the burst center. +burst_dx: +!byte 0,1,1,1,0,$ff,$ff,$ff,0,1,0,$ff,1,1,$ff,$ff +!byte 0,1,2,1,0,$ff,$fe,$ff,2,2,0,$fe,1,1,$ff,$ff +!byte 0,2,3,2,0,$fe,$fd,$fe,3,3,0,$fd,1,1,$ff,$ff +!byte 0,2,4,2,0,$fe,$fc,$fe,4,3,0,$fc,1,1,$ff,$ff +!byte 0,3,5,3,0,$fd,$fb,$fd,5,4,0,$fb,2,2,$fe,$fe +burst_dy: +!byte $ff,$ff,0,1,1,1,0,$ff,$ff,0,1,0,$ff,1,1,$ff +!byte $fe,$ff,0,1,2,1,0,$ff,$fe,0,2,0,$ff,1,1,$ff +!byte $fd,$fe,0,2,3,2,0,$fe,$fd,0,3,0,$ff,1,1,$ff +!byte $fc,$fe,0,2,4,2,0,$fe,$fc,0,4,0,$ff,1,1,$ff +!byte $fb,$fd,0,3,5,3,0,$fd,$fb,0,5,0,$fe,2,2,$fe + +burst_chars: !byte 81,42,43,46,46 +particle_colors: !byte 1,7,10,8,2,5,3,13,1,7,10,8,2,5,3,13 +star_x: !byte 2,5,8,11,14,17,20,23,26,29,32,35,38,4,10,27,34,16 +star_y: !byte 3,8,5,12,4,9,3,13,6,10,4,8,12,15,17,16,14,6 +building_height: +!byte 3,3,4,4,4,6,6,6,5,5,3,3,7,7,7,7,4,4,5,5 +!byte 5,8,8,8,6,6,4,4,4,7,7,7,5,5,6,6,6,3,3,3 +window_x: !byte 2,6,9,13,16,19,22,25,29,32,35,38 +window_y: !byte 23,21,22,20,23,22,19,21,20,22,21,23 + +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: !for i,0,24 { !byte <(COLOR+i*40) } +color_row_hi: !for i,0,24 { !byte >(COLOR+i*40) } + +show_state: !byte 0 +palette: !byte 0 +auto_show: !byte 0 +auto_countdown: !byte 0 +animation_speed: !byte 0 +tick: !byte 0 +last_jiffy: !byte 0 +seed: !byte 0 center_x: !byte 0 +rocket_x: !byte 0 rocket_y: !byte 0 -burst_color: !byte 0 -particle_index: !byte 0 -px: !byte 0 -char_value: !byte 0 +trail_length: !byte 0 +explosion_stage: !byte 0 +particle: !byte 0 +plot_x: !byte 0 +plot_y: !byte 0 +character: !byte 0 +character_color: !byte 0 +height_left: !byte 0 +object_index: !byte 0 old_border: !byte 0 old_background: !byte 0 +old_volume: !byte 0 +old_sid: !fill 7,0 diff --git a/fireworks/fireworks.prg b/fireworks/fireworks.prg index 2ee6082c1c4b407490b1f7a12169763ddf4f9b3d..a9c306241e0608aa8e7f389b43f1ab5dd07621ff 100644 GIT binary patch literal 1578 zcmaJ?U1(cn82-+0PR_}BlcxDOZP)c{1z9W0`ZIdr)nb~`u+XGQs`X~%&i10Z;V|&wi!Vl5WT`AtPY3 zEn^3drCc};fD?dm32Av`%GGQYNx46bJ{RErjH}oJ`nPr-_Ce!Q6gv)q6M~09*xbPB zLU0@gdPR2(X!vSEBa^-1M>!l~RXYG^@Gl=^Rl^E*!U==59(Kn^YSyOsi)F28tRGke z>m>ZKttcM)}-;^?XTTGkoefbgN0hitv~BHndw>P*D`YGXx6%gTpIyv z9d}^>_8$eTH5DfmmNfv-LrUM!tP<&8}-h=s(J8v zJzp+oM6S0?HVn4Kx35|?Fn%xy2gBh0_T=cC`>3b-k*E3zSGAYCJ@&)`?vG{M=}ecA zx*cOe-R@&@-3~I#TPOz4^WeKYs4=B(zt7a?X}Qkp*bsbp2JQ~R-e+c|xp&{JwDu0o zN_+2jv(mYXr#%GMn$8)x)-KyuD^1&|w5sIuW+Q-4;c?S_`nZ+7WZ*r=>-|?5PX^!4 z7~CXv@9j9FfEvyS;1hBv;4AW;Q2DxPnm6bRHlHb^-^dj%7fn;4Nt#cWim6P77B9a^ z=a;itnwzJoTsBvr$;CNZ%q=g@A;-rrP#{R<7E6U(7D;$!yO>X=(hAKcmlsnDh?7XY zT*{%BQhIb=omV?`enz3id^$ac=_Q3OEoVw7q3~qS7D}aj@zo0#QnMEm`RU2TT>5p> z+&aw`(%E#fh}~1OG?yynUP~9~^yKs`a%`X0(0n0XETRgIMRAT|DOo5HA_xNMcDn?B z1%ZD>^g3NpBpnZn5_;{9B$0Lx%ZOVYSt2bDOA2P1ZAB(cQS5X$gU5J6*g0h+q9@Sq zkRBtEJlsO;F%sFs%{J*V5`}b-aB1R|L_+ZCny5(T=~q-V1NtKI!D0H+%d$Q+7Lqh2 zAp0d#)nzRZ>>q4A<@o>r literal 431 zcmaKpJxIe)5XWDlwK=QkBn1agTvSk62RA_piej)|79AWiwu9i{;OG(%;Yo{&lSsfO zPy0ISP;fL3@(?!>3Ocll2qFmmh_7l_f5UPAyFbTqr)VLqmz>T-W}}1pLoJy z_{Z5E*>Um$gtH-UET`5+em#k#-YnEAzweQhqJ_Lo;R|OR!i=lZ<@At zMh-;tPJEg6l=$F9kZ0f=I+rkymsXOC8?oeS3NaO5&==8INU!P3h&t*qBbG!=U?RP; z-cN|4`mMj%@`+DWMNwsqjK}xRZr{W6ncP)Hi)`+@;tQ8|PHwt?3H;FWOR$an%@5zc CE~oSW diff --git a/programs.json b/programs.json index f601dd7..386f51c 100644 --- a/programs.json +++ b/programs.json @@ -151,8 +151,8 @@ }, { "title": "Fireworks", "category": "Demo", "language": "machine-code", "releaseDate": "2026-10-16", - "description": "Launch colorful PETSCII fireworks into a night sky.", - "controls": [{"keys":["SPACE"],"description":"Launch a firework"},{"keys":["C"],"description":"Choose the next burst color"},{"keys":["Q"],"description":"Return to BASIC"}], + "description": "Launch colorful, noisy PETSCII fireworks above a twinkling city skyline.", + "controls": [{"keys":["SPACE"],"description":"Launch a firework"},{"keys":["A"],"description":"Toggle the automatic fireworks show"},{"keys":["C"],"description":"Change color palette"},{"keys":["1","2","3"],"description":"Select animation speed"},{"keys":["Q"],"description":"Return to BASIC"}], "path": "fireworks/fireworks.prg", "source": "fireworks/fireworks.asm" }, {