diff options
Diffstat (limited to 'src/sound.s')
| -rw-r--r-- | src/sound.s | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/sound.s b/src/sound.s new file mode 100644 index 0000000..a824898 --- /dev/null +++ b/src/sound.s @@ -0,0 +1,171 @@ +.segment "CODE" + +;; The sound for this game is extremely simple, coming from a system that only +;; allowed for 1-bit beeps. Here the sound is a bit different due to a vastly +;; different audio hardware, and we make use of three channels: +;; +;; 1. Square 1: used on level entry and bullets. +;; 2. Square 2: used for item collection or dropping. +;; 3. Noise: enemy explosion and rocket launch. +.scope Sound + ;; Bullets can go super fast, and if we delivered the sound effect for each + ;; bullet it could potentially be annoying. Moreover, because of the + ;; limitations from the ZX Spectrum, the original game didn't spit a sound + ;; effect for each bullet either. Hence, wait for some frames before + ;; producing a sound. This is why we call Sound::tick() on NMI code, and why + ;; the sound effect for bullet is called via Sound::play_bullet_maybe(). + ;; + ;; NOTE: the maximum count value is supposed to be bigger than the timer for + ;; bullets creation. This is guaranteed in 'jetpac.s'. + zp_frame_count = $DA + BULLET_SFX_FRAME_COUNT = HZ / 10 + + ;; Period values for square channels. + .ifdef PAL + BULLET_SFX_LOW = $29 + BULLET_SFX_HIGH = $00 + ENTER_SFX_LOW = $4D + ENTER_SFX_HIGH = $01 + PICKUP_SFX_LOW = $61 + PICKUP_SFX_HIGH = $01 + DROP_SFX_LOW = $3A + DROP_SFX_HIGH = $01 + .else + BULLET_SFX_LOW = $2C + BULLET_SFX_HIGH = $00 + ENTER_SFX_LOW = $67 + ENTER_SFX_HIGH = $01 + PICKUP_SFX_LOW = $7C + PICKUP_SFX_HIGH = $01 + DROP_SFX_LOW = $52 + DROP_SFX_HIGH = $01 + .endif + + ;; Initialize all the sound channels which are needed and reset some + ;; register values. + .proc init + ;; Enable square 1, 2; and noise. + lda #%00001011 + sta APU::m_status + + ;; Reset sweep registers and frame count. + lda #0 + sta APU::m_square_1_sweep + sta APU::m_square_2_sweep + sta Sound::zp_frame_count + + ;; Silence channels. + lda #0 + sta APU::m_noise_envelope + lda #$30 + sta APU::m_square_1_envelope + sta APU::m_square_2_envelope + + rts + .endproc + + ;; Tick the internal frame count for sound effects. + ;; + ;; NOTE: expected to only be called at the end of NMI code. + .proc tick + ;; If there is no bullet sound effect to be delivered, don't even sweat + ;; it. + lda Sound::zp_frame_count + beq @end + + ;; Increase the frame counter and check the limit. If we reached that + ;; limit, reset it so we don't tick until the next bullet sfx request + ;; comes in. + clc + adc #1 + cmp #Sound::BULLET_SFX_FRAME_COUNT + beq @reset + sta Sound::zp_frame_count + rts + + @reset: + lda #0 + sta Sound::zp_frame_count + + @end: + rts + .endproc + + ;; Play the bullet sound effect if we can (i.e. the frame count allows us to + ;; do it). + .proc play_bullet_maybe + ;; If we cannot play the sound yet, skip this altogether. + lda Sound::zp_frame_count + bne @end + inc Sound::zp_frame_count + + lda #$01 + sta APU::m_square_1_envelope + lda #%10000001 + sta APU::m_square_1_sweep + lda #BULLET_SFX_LOW + sta APU::m_square_1_low + lda #BULLET_SFX_HIGH + sta APU::m_square_1_high + + @end: + rts + .endproc +.endscope + +;; Make an explosion sound via the noise channel. +.macro SOUND_EXPLOSION + lda #$03 + sta APU::m_noise_envelope + lda #$8F + sta APU::m_noise_mode + lda #$F8 + sta APU::m_noise_counter +.endmacro + +;; Make a small beep, suitable for level entry. +.macro SOUND_ENTER_LEVEL + lda #%10000100 + sta APU::m_square_1_envelope + lda #Sound::ENTER_SFX_LOW + sta APU::m_square_1_low + lda #Sound::ENTER_SFX_HIGH + sta APU::m_square_1_high +.endmacro + +;; Make a small beep for item pickup. +.macro SOUND_ITEM_PICKUP + lda #%10000100 + sta APU::m_square_2_envelope + lda #Sound::PICKUP_SFX_LOW + sta APU::m_square_2_low + lda #Sound::PICKUP_SFX_HIGH + sta APU::m_square_2_high +.endmacro + +;; Make a small beep for item collection in the droppping zone (i.e. fuel tanks +;; and shuttle parts making into the shuttle). +.macro SOUND_ITEM_DROP + lda #%10000100 + sta APU::m_square_2_envelope + lda #Sound::DROP_SFX_LOW + sta APU::m_square_2_low + lda #Sound::DROP_SFX_HIGH + sta APU::m_square_2_high +.endmacro + +;; Start the sound effect for the rocket take off animation. +.macro START_TAKE_OFF_SOUND + lda #$38 + sta APU::m_noise_envelope + lda #$0F + sta APU::m_noise_mode + lda #0 + sta APU::m_noise_counter +.endmacro + +;; Stop the sound effect for the rocket take off animation. +.macro STOP_TAKE_OFF_SOUND + lda #0 + sta APU::m_noise_envelope +.endmacro |
