sounds, menu tweaks

This commit is contained in:
2026-07-16 10:42:57 +02:00
parent 88922bd932
commit f2bf6ba6ad
5 changed files with 174 additions and 9 deletions
+18
View File
@@ -26,6 +26,24 @@ SPR_XEX = $d01d ; horizontal expand
SPR_COL = $d027 ; sprite 0 color, +1 = sprite 1, ... SPR_COL = $d027 ; sprite 0 color, +1 = sprite 1, ...
; ---- SID registers (voice 1 used for SFX) ----
SID_V1FL = $d400 ; voice 1 frequency low
SID_V1FH = $d401 ; voice 1 frequency high
SID_V1PL = $d402 ; voice 1 pulse width low
SID_V1PH = $d403 ; voice 1 pulse width high
SID_V1CR = $d404 ; voice 1 control (waveform + gate)
SID_V1AD = $d405 ; voice 1 attack/decay
SID_V1SR = $d406 ; voice 1 sustain/release
SID_VOL = $d418 ; filter mode + master volume
; ---- SFX IDs ----
SFX_SCORE = 0 ; rabbit dodged: high pling
SFX_MISS = 1 ; rabbit hit: noise crash
SFX_OVER = 2 ; game over: descending sweep
SFX_CURSOR = 3 ; menu cursor move: click
SFX_SELECT = 4 ; menu fire: rising tone
NSFX = 5
; ---- colors ---- ; ---- colors ----
BLACK = 0 BLACK = 0
WHITE = 1 WHITE = 1
+3
View File
@@ -61,6 +61,7 @@ sprcol:
sta SPR_YEX sta SPR_YEX
sta framectr sta framectr
sta fheld sta fheld
jsr sfx_init
!ifdef AUTOPLAY { ; test builds boot straight into the game !ifdef AUTOPLAY { ; test builds boot straight into the game
jsr play_init jsr play_init
@@ -78,6 +79,7 @@ main:
sta BG sta BG
inc framectr inc framectr
jsr rand8 ; stir the RNG once per frame jsr rand8 ; stir the RNG once per frame
jsr sfx_update ; advance sound effects
jsr call_update ; finishes long before the horizon line jsr call_update ; finishes long before the horizon line
wait_grass: wait_grass:
lda RASTER ; split the background at the horizon: lda RASTER ; split the background at the horizon:
@@ -121,4 +123,5 @@ wf_hit:
!src "play.asm" !src "play.asm"
!src "over.asm" !src "over.asm"
!src "common.asm" !src "common.asm"
!src "sound.asm"
!src "tables.asm" !src "tables.asm"
+12 -9
View File
@@ -79,12 +79,16 @@ menu_update:
lda menusel lda menusel
beq mu_udend beq mu_udend
dec menusel dec menusel
lda #SFX_CURSOR
jsr sfx_play
jmp mu_udend jmp mu_udend
mu_down: mu_down:
lda menusel lda menusel
cmp #MENU_ITEMS-1 cmp #MENU_ITEMS-1
beq mu_udend beq mu_udend
inc menusel inc menusel
lda #SFX_CURSOR
jsr sfx_play
jmp mu_udend jmp mu_udend
mu_udrel: mu_udrel:
lda #0 lda #0
@@ -155,15 +159,9 @@ mu_keyup:
sta k12held sta k12held
mu_keydone: mu_keydone:
; footer: the two control lines take turns ; footer: both control lines always visible
lda framectr
and #64
beq mu_foot2
+prtext 22, 9, LGREY, txt_info, 21 +prtext 22, 9, LGREY, txt_info, 21
jmp mu_footdone +prtext 23, 9, LGREY, txt_info2, 21
mu_foot2:
+prtext 22, 9, LGREY, txt_info2, 21
mu_footdone:
; the menu items: the picked line is yellow ; the menu items: the picked line is yellow
ldx #0 ldx #0
@@ -206,6 +204,8 @@ mu_start:
jsr start_edge jsr start_edge
beq mu_done beq mu_done
menu_go: menu_go:
lda #SFX_SELECT
jsr sfx_play
lda menusel lda menusel
cmp #2 cmp #2
beq mg_credits beq mg_credits
@@ -238,8 +238,10 @@ draw_mitem:
lda #YELLOW lda #YELLOW
dm_store: dm_store:
sta pcolor sta pcolor
stx rtmp ; print_text trashes X
jsr print_text jsr print_text
ldy #0 ; recolor the first letter (shortcut key) ldx rtmp
ldy mitem_key,x ; recolor the shortcut letter
lda #CYAN lda #CYAN
sta (collo),y sta (collo),y
rts rts
@@ -248,6 +250,7 @@ dm_store:
MENU_ITEMS = 4 MENU_ITEMS = 4
mitem_lo: !byte <txt_1p, <txt_2p, <txt_credits, <txt_story mitem_lo: !byte <txt_1p, <txt_2p, <txt_credits, <txt_story
mitem_hi: !byte >txt_1p, >txt_2p, >txt_credits, >txt_story mitem_hi: !byte >txt_1p, >txt_2p, >txt_credits, >txt_story
mitem_key: !byte 0, 0, 0, 1 ; offset of the highlighted shortcut letter
mitem_len: !byte 13, 11, 7, 5 mitem_len: !byte 13, 11, 7, 5
mitem_row: !byte 14, 16, 18, 20 mitem_row: !byte 14, 16, 18, 20
mcur_lo: ; cursor cells: column 12 of those rows mcur_lo: ; cursor cells: column 12 of those rows
+6
View File
@@ -257,6 +257,8 @@ pu_rnext:
lda miss lda miss
cmp #MAX_MISS cmp #MAX_MISS
bcc pu_done bcc pu_done
lda #SFX_OVER
jsr sfx_play
jmp over_init ; its rts returns to the main loop jmp over_init ; its rts returns to the main loop
pu_done: pu_done:
rts rts
@@ -423,6 +425,8 @@ at_done:
; ---- score: bump the decimal digits and the difficulty byte ---- ; ---- score: bump the decimal digits and the difficulty byte ----
add_score: add_score:
lda #SFX_SCORE
jsr sfx_play
lda score8 lda score8
cmp #$ff cmp #$ff
beq as_digits beq as_digits
@@ -461,6 +465,8 @@ draw_score:
; ---- miss: X mark on the HUD + blink the scooter ---- ; ---- miss: X mark on the HUD + blink the scooter ----
add_miss: add_miss:
lda #SFX_MISS
jsr sfx_play
inc miss inc miss
ldy miss ; Y: the rabbit loop still needs X ldy miss ; Y: the rabbit loop still needs X
lda #24 ; 'x' lda #24 ; 'x'
+135
View File
@@ -0,0 +1,135 @@
; -----------------------------------------------------------
; sound.asm - minimal SID sound driver using voice 1
; sfx_init - set master volume, silence voice 1
; sfx_play - start effect A (SFX_SCORE, SFX_MISS, etc.)
; sfx_update - call once per frame to handle duration/slides
; -----------------------------------------------------------
; ---- one-time setup: master volume on, voice 1 silent ----
sfx_init:
lda #$0f ; max volume, no filter
sta SID_VOL
lda #0
sta SID_V1CR ; gate off, no waveform
sta sfx_timer
rts
; ---- start playing effect A ----
sfx_play:
tax
; gate off first (retrigger envelope)
lda #0
sta SID_V1CR
; load parameters from the table
lda sfx_flo,x
sta SID_V1FL
lda sfx_fhi,x
sta SID_V1FH
lda sfx_ad,x
sta SID_V1AD
lda sfx_sr,x
sta SID_V1SR
lda #$00 ; pulse width mid-point for pulse wave
sta SID_V1PL
lda #$08
sta SID_V1PH
lda sfx_wave,x ; waveform + gate bit
sta SID_V1CR
lda sfx_dur,x
sta sfx_timer
lda sfx_slide,x
sta sfx_sld
rts
; ---- per-frame update: pitch slide + gate off when done ----
sfx_update:
lda sfx_timer
beq sfu_done ; nothing playing
dec sfx_timer
bne sfu_slide
; duration expired: gate off
lda #0
sta SID_V1CR
rts
sfu_slide:
; apply pitch slide (signed: positive = up, negative = down)
lda sfx_sld
beq sfu_done
bmi sfu_down
; slide up
clc
adc SID_V1FH
sta SID_V1FH
rts
sfu_down:
; slide down (sfx_sld is negative, e.g. $fe = -2)
clc
adc SID_V1FH ; adding a negative = subtracting
sta SID_V1FH
bcs sfu_done ; no underflow
lda #0
sta SID_V1FH ; clamp at zero
sfu_done:
rts
; ---- effect parameter tables (indexed by SFX ID) ----
; initial frequency low byte
sfx_flo:
!byte $00 ; SFX_SCORE: freq $1C00
!byte $00 ; SFX_MISS: freq $0800
!byte $00 ; SFX_OVER: freq $2000
!byte $00 ; SFX_CURSOR: freq $0A00
!byte $00 ; SFX_SELECT: freq $1000
; initial frequency high byte
sfx_fhi:
!byte $1c ; SFX_SCORE
!byte $08 ; SFX_MISS
!byte $20 ; SFX_OVER
!byte $0a ; SFX_CURSOR
!byte $10 ; SFX_SELECT
; attack/decay ($XY: X=attack 0-F, Y=decay 0-F)
sfx_ad:
!byte $00 ; SFX_SCORE: instant attack, instant decay
!byte $00 ; SFX_MISS: instant attack, instant decay
!byte $09 ; SFX_OVER: instant attack, slow decay
!byte $00 ; SFX_CURSOR: instant attack, instant decay
!byte $00 ; SFX_SELECT: instant attack, instant decay
; sustain/release ($XY: X=sustain 0-F, Y=release 0-F)
sfx_sr:
!byte $a8 ; SFX_SCORE: medium sustain, medium release
!byte $f5 ; SFX_MISS: full sustain, medium release
!byte $08 ; SFX_OVER: zero sustain, medium release
!byte $50 ; SFX_CURSOR: low sustain, instant release
!byte $98 ; SFX_SELECT: medium sustain, medium release
; waveform + gate ($XY: bit7=noise, bit6=pulse, bit5=saw, bit4=tri, bit0=gate)
sfx_wave:
!byte $11 ; SFX_SCORE: triangle + gate
!byte $81 ; SFX_MISS: noise + gate
!byte $21 ; SFX_OVER: sawtooth + gate
!byte $41 ; SFX_CURSOR: pulse + gate
!byte $11 ; SFX_SELECT: triangle + gate
; duration in frames
sfx_dur:
!byte 8 ; SFX_SCORE
!byte 10 ; SFX_MISS
!byte 50 ; SFX_OVER
!byte 3 ; SFX_CURSOR
!byte 8 ; SFX_SELECT
; pitch slide per frame (signed: + = up, - = down, 0 = none)
sfx_slide:
!byte 0 ; SFX_SCORE: steady
!byte $fe ; SFX_MISS: slide down (-2)
!byte $fd ; SFX_OVER: slide down (-3)
!byte 0 ; SFX_CURSOR: steady
!byte 2 ; SFX_SELECT: slide up (+2)
; ---- driver state ----
sfx_timer: !byte 0 ; frames remaining for current effect
sfx_sld: !byte 0 ; current slide value