Skip to content

Commit

Permalink
Reduce music volume when paused, using console, or in a building
Browse files Browse the repository at this point in the history
  • Loading branch information
mdsteele committed Oct 1, 2024
1 parent ffb057f commit 6342890
Show file tree
Hide file tree
Showing 31 changed files with 127 additions and 72 deletions.
5 changes: 2 additions & 3 deletions nsf/nsf.asm
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,8 @@ kSoundChip = 0 ; 0 = no extra sound chips
.assert eMusic::Silence = 0, error
iny
sty Zp_Next_sAudioCtrl + sAudioCtrl::Music_eMusic
lda #$ff
sta Zp_Next_sAudioCtrl + sAudioCtrl::Enable_bool
sta Zp_Next_sAudioCtrl + sAudioCtrl::MasterVolume_u8
lda #bAudio::Enable
sta Zp_Next_sAudioCtrl + sAudioCtrl::Next_bAudio
jmp Func_AudioSync
.ENDPROC

Expand Down
34 changes: 16 additions & 18 deletions src/audio.asm
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ Zp_Next_sAudioCtrl: .tag sAudioCtrl
.EXPORTZP Zp_Next_sChanSfx_arr
Zp_Next_sChanSfx_arr: .res .sizeof(sChanSfx) * kNumApuChannels

;;; The current settings for whether audio is enabled.
.EXPORTZP Zp_Current_bAudio
Zp_Current_bAudio: .res 1

;;; The currently-playing music.
Zp_Current_eMusic: .res 1

Expand All @@ -89,16 +93,6 @@ Zp_Current_sMusic: .tag sMusic
;;; indexing by APU channel number.
Zp_Music_sChanNext_arr: .res .sizeof(sChanNext) * kNumApuChannels

;;; If true ($ff), then Func_AudioUpdate will perform audio playback; if false
;;; ($00), then Func_AudioUpdate is a no-op. Invariant: all APU channels are
;;; disabled when this is false.
Zp_AudioEnabled_bool: .res 1

;;; Master volume that is applied to all channels in conjunction with their
;;; individual volume envelopes. The bottom four bits of this variable are
;;; always zero.
Zp_MasterVolume_u8: .res 1

;;; This must be all zero bits except for bMusic::FlagMask; those bits indicate
;;; the current music flag value.
Zp_MusicFlag_bMusic: .res 1
Expand Down Expand Up @@ -165,7 +159,7 @@ Ram_Sound_sChanSfx_arr: .res .sizeof(sChanSfx) * kNumApuChannels
dex
bpl @loop
;; Disable audio and reset music flag.
sta Zp_AudioEnabled_bool
sta Zp_Current_bAudio
sta Zp_MusicFlag_bMusic
_HaltMusic:
.assert eMusic::Silence = 0, error
Expand All @@ -186,17 +180,16 @@ _HaltSfx:
;;; @prereq Caller is within the NMI handler, and Func_ProcessFrame is pending.
.EXPORT Func_AudioSync
.PROC Func_AudioSync
lda <(Zp_Next_sAudioCtrl + sAudioCtrl::Enable_bool)
lda Zp_Next_sAudioCtrl + sAudioCtrl::Next_bAudio
.assert bAudio::Enable = bProc::Negative, error
bmi _Enable
_Disable:
bit Zp_AudioEnabled_bool
bit Zp_Current_bAudio
.assert bAudio::Enable = bProc::Negative, error
bmi Func_AudioReset
rts
_Enable:
sta Zp_AudioEnabled_bool
lda <(Zp_Next_sAudioCtrl + sAudioCtrl::MasterVolume_u8)
and #$f0
sta Zp_MasterVolume_u8
sta Zp_Current_bAudio
_SyncMusicFlag:
lda Zp_Next_sAudioCtrl + sAudioCtrl::MusicFlag_bMusic
.assert bMusic::UsesFlag = bProc::Negative, error
Expand Down Expand Up @@ -299,7 +292,8 @@ _ResetChannels:
;;; @prereq Caller is within the NMI handler.
.EXPORT Func_AudioUpdate
.PROC Func_AudioUpdate
bit Zp_AudioEnabled_bool
bit Zp_Current_bAudio
.assert bAudio::Enable = bProc::Negative, error
bmi _Enabled
rts
_Enabled:
Expand Down Expand Up @@ -532,6 +526,10 @@ _NoteToneOrSame:
cpx #eChan::Dmc
bne @notDmc
@isDmc:
;; Skip DMC notes entirely when music volume is reduced.
bit Zp_Current_bAudio
.assert bAudio::ReduceMusic = bProc::Overflow, error
bvs _SkipToneOrSame
lda #$40
bne @setSweep ; unconditional
@notDmc:
Expand Down
30 changes: 20 additions & 10 deletions src/audio.inc
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,20 @@

;;;=========================================================================;;;

;;; Flags for controlling whether audio is enabled.
.SCOPE bAudio
;; Controls whether audio is enabled. When audio is disabled, all music
;; and sound effects are stopped, all APU channels are muted, and the audio
;; driver will not read any more audio data until audio is re-enabled.
;; Note that since this game generally stores music data in PRGC, it is
;; only safe to switch PRGC banks when audio is disabled.
Enable = %10000000
;; Controls the music volume. When this bit is set, certain music
;; instruments will play at reduced volume or not at all. Sound effects
;; are unaffected.
ReduceMusic = %01000000
.ENDSCOPE

;;; Instructions to be sent to the audio driver the next time Func_ProcessFrame
;;; is called.
.STRUCT sAudioCtrl
Expand All @@ -78,22 +92,18 @@
;; driver will not read any more audio data until audio is re-enabled.
;; Note that since this game generally stores music data in PRGC, it is
;; only safe to switch PRGC banks when audio is disabled.
Enable_bool .byte
;; Sets the master volume (0-255). This should normally be left at 255
;; (full volume), but can be reduced over the course of several frames to
;; fade out audio before disabling it. Note that only the top four bits
;; are actually used.
MasterVolume_u8 .byte
Next_bAudio .byte
;; Controls which music to play. When Func_ProcessFrame is called, if this
;; is different than the currently-playing music (and audio is enabled),
;; then the current music will be stopped, and this music will be started
;; from the beginning.
Music_eMusic .byte
;; Controls the music flag. If bMusic::UsesFlag is set, then the music
;; flag will be set to this & bMusic::FlagMask when Func_ProcessFrame is
;; called; otherwise, the music flag will be unchanged. Either way, this
;; field will be updated to the (new) current value of the of the music
;; flag when Func_ProcessFrame is called.
MusicFlag_bMusic .byte
;; Controls which music to play. When Func_ProcessFrame is called, if this
;; is different than the currently-playing music, then the current music
;; will be stopped, and this music will be started from the beginning.
Music_eMusic .byte
.ENDSTRUCT

;;;=========================================================================;;;
7 changes: 7 additions & 0 deletions src/console.asm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
;;; with Annalog. If not, see <http://www.gnu.org/licenses/>. ;;;
;;;=========================================================================;;;

.INCLUDE "audio.inc"
.INCLUDE "avatar.inc"
.INCLUDE "charmap.inc"
.INCLUDE "console.inc"
Expand Down Expand Up @@ -55,6 +56,7 @@
.IMPORT Func_ProcessFrame
.IMPORT Func_SetLastSpawnPoint
.IMPORT Func_SetMachineIndex
.IMPORT Func_SetMusicVolumeForCurrentRoom
.IMPORT Func_TickAllDevices
.IMPORT Func_Window_GetRowPpuAddr
.IMPORT Func_Window_PrepareRowTransfer
Expand All @@ -78,6 +80,7 @@
.IMPORTZP Zp_Current_sProgram_ptr
.IMPORTZP Zp_FloatingHud_bHud
.IMPORTZP Zp_MachineMaxInstructions_u8
.IMPORTZP Zp_Next_sAudioCtrl
.IMPORTZP Zp_P1ButtonsPressed_bJoypad
.IMPORTZP Zp_PpuTransferLen_u8
.IMPORTZP Zp_ScrollGoalX_u16
Expand Down Expand Up @@ -219,6 +222,7 @@ _UpdateScrolling:
_Done:
lda #$ff
sta Zp_ConsoleMachineIndex_u8
jsr Func_SetMusicVolumeForCurrentRoom
jmp Main_Explore_Continue
.ENDPROC

Expand Down Expand Up @@ -280,6 +284,9 @@ _Tick:
;;; and resets the machine if it's not Halted/Error.
;;; @param X The console device index.
.PROC FuncA_Room_BeginUsingConsoleDevice
;; Reduce music volume while the console is open.
lda #bAudio::Enable | bAudio::ReduceMusic
sta Zp_Next_sAudioCtrl + sAudioCtrl::Next_bAudio
_SetSpawnPoint:
txa ; console device index
ora #bSpawn::Device ; param: bSpawn value
Expand Down
7 changes: 7 additions & 0 deletions src/inst.asm
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

.INCLUDE "apu.inc"
.INCLUDE "audio.inc"
.INCLUDE "cpu.inc"
.INCLUDE "inst.inc"
.INCLUDE "macros.inc"
.INCLUDE "music.inc"
Expand All @@ -27,6 +28,7 @@
.IMPORT Ram_Music_sChanNote_arr
.IMPORTZP Zp_AudioTmp1_byte
.IMPORTZP Zp_AudioTmp2_byte
.IMPORTZP Zp_Current_bAudio

;;;=========================================================================;;;

Expand Down Expand Up @@ -166,6 +168,11 @@ _Decay:
;;; @return A The duty/envelope byte to use.
;;; @preserve X
.PROC Func_CombineVolumeWithDuty
bit Zp_Current_bAudio
.assert bAudio::ReduceMusic = bProc::Overflow, error
bvc @noReduce
div #2
@noReduce:
sta Zp_AudioTmp1_byte ; volume
lda Ram_Music_sChanInst_arr + sChanInst::Param_byte, x
and #bEnvelope::DutyMask
Expand Down
18 changes: 13 additions & 5 deletions src/pause.asm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
;;; with Annalog. If not, see <http://www.gnu.org/licenses/>. ;;;
;;;=========================================================================;;;

.INCLUDE "audio.inc"
.INCLUDE "charmap.inc"
.INCLUDE "cpu.inc"
.INCLUDE "devices/flower.inc"
Expand Down Expand Up @@ -55,6 +56,7 @@
.IMPORT Func_FillLowerAttributeTable
.IMPORT Func_FillUpperAttributeTable
.IMPORT Func_IsFlagSet
.IMPORT Func_SetMusicVolumeForCurrentRoom
.IMPORT Func_Window_Disable
.IMPORT Func_Window_ScrollDown
.IMPORT Func_Window_ScrollUp
Expand All @@ -72,6 +74,7 @@
.IMPORTZP Zp_Current_sRoom
.IMPORTZP Zp_FrameCounter_u8
.IMPORTZP Zp_NextIrq_int_ptr
.IMPORTZP Zp_Next_sAudioCtrl
.IMPORTZP Zp_P1ButtonsPressed_bJoypad
.IMPORTZP Zp_PaperCursorRow_u8
.IMPORTZP Zp_PpuScrollX_u8
Expand Down Expand Up @@ -131,7 +134,7 @@ Zp_ActivatedBreakers_byte: .res 1
main_chr0c_bank Ppu_ChrBgMinimap
main_chr18_bank Ppu_ChrObjPause
jsr FuncA_Pause_InitAndFadeIn
.assert * = MainA_Pause_Minimap, error, "fallthrough"
fall MainA_Pause_Minimap
.ENDPROC

;;; Mode for running the pause screen while the minimap is visible.
Expand All @@ -151,13 +154,14 @@ _CheckForUnpause:
lda Zp_P1ButtonsPressed_bJoypad
and #bJoypad::Start | bJoypad::BButton
beq _GameLoop
.assert * = MainA_Pause_FadeOut, error, "fallthrough"
fall MainA_Pause_FadeOut
.ENDPROC

;;; Mode for fading out the pause screen and resuming explore mode.
;;; @prereq Rendering is enabled.
.PROC MainA_Pause_FadeOut
jsr Func_FadeOutToBlack
jsr Func_SetMusicVolumeForCurrentRoom
jmp Main_Explore_FadeIn
.ENDPROC

Expand All @@ -174,7 +178,7 @@ _GameLoop:
jsr Func_Window_ScrollUp ; sets C if fully scrolled in
bcc _GameLoop
jsr FuncA_Pause_MovePaperCursorNext
.assert * = MainA_Pause_Papers, error, "fallthrough"
fall MainA_Pause_Papers
.ENDPROC

;;; Mode for running the pause screen while the papers window is visible.
Expand Down Expand Up @@ -246,6 +250,10 @@ _InitActivatedBreakers:
dex
cpx #kFirstBreakerFlag
bge @loop
_ReduceMusic:
;; Reduce music volume while on the pause screen.
lda #bAudio::Enable | bAudio::ReduceMusic
sta Zp_Next_sAudioCtrl + sAudioCtrl::Next_bAudio
_DrawScreen:
ldy #$00 ; param: fill byte
jsr Func_FillUpperAttributeTable ; preserves Y
Expand Down Expand Up @@ -385,7 +393,7 @@ _FinishLowerNametable:
bne @loop
jsr FuncA_Pause_DirectDrawWindowBottomBorder
ldy #kScreenWidthTiles * 5 ; param: num blank tiles to draw
.assert * = FuncA_Pause_DirectDrawBlankTiles, error, "fallthrough"
fall FuncA_Pause_DirectDrawBlankTiles
.ENDPROC

;;; Draws the specified number of blank BG tiles to Hw_PpuData_rw.
Expand Down Expand Up @@ -520,7 +528,7 @@ _CircuitBreakers_byte_arr8_arr6:
jsr FuncA_Pause_DirectDrawWindowLineSide ; preserves X and T0+
ldy #kScreenWidthTiles - 6 ; param: num blank tiles to draw
jsr FuncA_Pause_DirectDrawBlankTiles ; preserves X and T0+
.assert * = FuncA_Pause_DirectDrawWindowLineSide, error, "fallthrough"
fall FuncA_Pause_DirectDrawWindowLineSide ; preserves X and T0+
.ENDPROC

;;; Draws the left or right side of one pause window line, including margins;
Expand Down
2 changes: 1 addition & 1 deletion src/prologue.asm
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ Ppu_PrologueTextRow3Start = Ppu_Nametable0_sName + sName::Tiles_u8_arr + \
jsr Func_ClearRestOfOam
;; Disable audio.
lda #0
sta Zp_Next_sAudioCtrl + sAudioCtrl::Enable_bool
sta Zp_Next_sAudioCtrl + sAudioCtrl::Next_bAudio
jsr Func_ProcessFrame
;; Clear the upper nametable.
ldxy #Ppu_Nametable0_sName ; param: nametable addr
Expand Down
21 changes: 17 additions & 4 deletions src/room.asm
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,19 @@ Zp_RoomState: .res kRoomStateSize

.SEGMENT "PRG8"

;;; Enables audio and sets the music volume according to the current room's
;;; bRoom::ReduceMusic flag.
.EXPORT Func_SetMusicVolumeForCurrentRoom
.PROC Func_SetMusicVolumeForCurrentRoom
lda Zp_Current_sRoom + sRoom::Flags_bRoom
and #bRoom::ReduceMusic
.assert bRoom::ReduceMusic << 1 = bAudio::ReduceMusic, error
asl a
ora #bAudio::Enable
sta Zp_Next_sAudioCtrl + sAudioCtrl::Next_bAudio
rts
.ENDPROC

;;; Queues up the music for the specified room (if it's not already playing),
;;; switches PRGC banks, then loads and initializes data for the room.
;;; @prereq Rendering is disabled.
Expand Down Expand Up @@ -641,13 +654,13 @@ _PrisonMusic:
cpy Zp_Next_sAudioCtrl + sAudioCtrl::Music_eMusic
beq @done
lda #0
sta Zp_Next_sAudioCtrl + sAudioCtrl::Enable_bool
sta Zp_Next_sAudioCtrl + sAudioCtrl::Next_bAudio
sty T1 ; eMusic to play
stx T0
jsr Func_ProcessFrame ; preserves T0+
ldx T0
lda #$ff
sta Zp_Next_sAudioCtrl + sAudioCtrl::Enable_bool
lda #bAudio::Enable
sta Zp_Next_sAudioCtrl + sAudioCtrl::Next_bAudio
lda T1 ; eMusic to play
sta Zp_Next_sAudioCtrl + sAudioCtrl::Music_eMusic
@done:
Expand Down Expand Up @@ -889,7 +902,7 @@ _SetVars:
stx Zp_AvatarPlatformIndex_u8
stx Zp_ConsoleMachineIndex_u8
stx Zp_FloatingHud_bHud ; disable the floating HUD
rts
jmp Func_SetMusicVolumeForCurrentRoom
.ENDPROC

;;; Calls the current room's Tick_func_ptr function.
Expand Down
18 changes: 14 additions & 4 deletions src/room.inc
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,20 @@ kMaxPassages = 8

;;; Flag bits for a room.
.SCOPE bRoom
Unsafe = %10000000 ; while set, this room won't be set as spawn point
Tall = %01000000 ; if set, room is kTallRoomHeightBlocks blocks tall
ShareState = %00100000 ; don't zero room state between two rooms with this
AreaMask = %00001111 ; mask for this room's eArea value
;; When set, passages and devices in this room won't be set as safe spawn
;; points. This can be dynamically disabled for a room (e.g. when a boss
;; is defeated) by calling Func_MarkRoomSafe.
Unsafe = %10000000
;; If set, this room's terrain is kTallRoomHeightBlocks blocks tall instead
;; of kScreenHeightBlocks blocks tall.
Tall = %01000000
;; If set, music is played at a reduced volume in this room.
ReduceMusic = %00100000
;; If two rooms both have this bit set, then Zp_RoomState will not be
;; zeroed by default when moving directly between those two rooms.
ShareState = %00010000
;; Bits used for storing this room's eArea value.
AreaMask = %00001111
.ENDSCOPE

;;; Assert that an eArea value will fit into the AreaMask.
Expand Down
2 changes: 1 addition & 1 deletion src/rooms/city_building1.asm
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
D_STRUCT sRoom
d_byte MinScrollX_u8, $0
d_word MaxScrollX_u16, $0
d_byte Flags_bRoom, eArea::City
d_byte Flags_bRoom, bRoom::ReduceMusic | eArea::City
d_byte MinimapStartRow_u8, 2
d_byte MinimapStartCol_u8, 17
d_addr TerrainData_ptr, _TerrainData
Expand Down
2 changes: 1 addition & 1 deletion src/rooms/city_building2.asm
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ kPerDigitSpinFrames = 10
D_STRUCT sRoom
d_byte MinScrollX_u8, $0
d_word MaxScrollX_u16, $0
d_byte Flags_bRoom, bRoom::ShareState | eArea::City
d_byte Flags_bRoom, bRoom::ReduceMusic | bRoom::ShareState | eArea::City
d_byte MinimapStartRow_u8, 1
d_byte MinimapStartCol_u8, 19
d_addr TerrainData_ptr, _TerrainData
Expand Down
Loading

0 comments on commit 6342890

Please sign in to comment.