Skip to content

Commit b608f29

Browse files
authored
Play a quieter music box track outside of the hotel lobby (#1181)
1 parent a1af446 commit b608f29

File tree

7 files changed

+150
-2
lines changed

7 files changed

+150
-2
lines changed

Common/Settings.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
visit(MemoScreenFix, true) \
109109
visit(MenuSoundsFix, true) \
110110
visit(MothDrawOrderFix, true) \
111+
visit(MusicBoxVolume, true) \
111112
visit(NoCDPatch, true) \
112113
visit(ObservationDeckFogFix, true) \
113114
visit(OldManCoinFix, true) \
@@ -263,6 +264,7 @@
263264
visit(LimitPerFrameFPS) \
264265
visit(LoadModulesFromMemory) \
265266
visit(LockResolution) \
267+
visit(MusicBoxVolume) \
266268
visit(NormalFontHeight) \
267269
visit(NormalFontWidth) \
268270
visit(OldManCoinFix) \

Patches/MusicBoxVolume.cpp

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/**
2+
* Copyright (C) 2025 Murugo
3+
*
4+
* This software is provided 'as-is', without any express or implied warranty. In no event will the
5+
* authors be held liable for any damages arising from the use of this software.
6+
* Permission is granted to anyone to use this software for any purpose, including commercial
7+
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
8+
*
9+
* 1. The origin of this software must not be misrepresented; you must not claim that you wrote the
10+
* original software. If you use this software in a product, an acknowledgment in the product
11+
* documentation would be appreciated but is not required.
12+
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented as
13+
* being the original software.
14+
* 3. This notice may not be removed or altered from any source distribution.
15+
*/
16+
17+
#define WIN32_LEAN_AND_MEAN
18+
#include <Windows.h>
19+
#include "Patches.h"
20+
#include "Common\Utils.h"
21+
#include "Logging\Logging.h"
22+
23+
namespace
24+
{
25+
// Game flag set after unlocking the music box in the Lakeview Hotel 1F lobby.
26+
constexpr int kMusicBoxSolvedFlag = 0x1D8;
27+
28+
// Variables for ASM
29+
BYTE* GameFlagAddr = 0;
30+
DWORD BgmChangeReturnAddr = 0;
31+
void(*shBgmCall)(int);
32+
33+
bool IsHotelMusicBoxSolved()
34+
{
35+
return GameFlagAddr[kMusicBoxSolvedFlag >> 3] & (1 << (kMusicBoxSolvedFlag & 0x07));
36+
}
37+
38+
// Returns the BGM bank index to use for Lakeview Hotel 2F.
39+
int GetStageBgmBank()
40+
{
41+
return IsHotelMusicBoxSolved() ? 4 : 0;
42+
}
43+
44+
// Loads "sound\adx\hotel\bgm_112.aix" for Lakeview Hotel 2F if the music box puzzle is solved.
45+
// Otherwise, loads "sound\adx\hotel\bgm_121.aix" as the default.
46+
__declspec(naked) void __stdcall BgmChangeASM()
47+
{
48+
__asm
49+
{
50+
cmp ecx, 0x29
51+
jne ExitAsm
52+
call IsHotelMusicBoxSolved
53+
test al, al
54+
jz ExitAsm
55+
push 0x22
56+
call shBgmCall
57+
add esp, 0x04
58+
pop ebx
59+
ret
60+
61+
ExitAsm:
62+
add ecx, -0x02
63+
cmp ecx, 0x38
64+
jmp BgmChangeReturnAddr
65+
}
66+
}
67+
}
68+
69+
// Plays a quieter version of the music box in certain rooms of the Lakeview Hotel.
70+
// This assumes that the quieter BGM is track 7 of "sound\adx\hotel\bgm_112.aix" (this track is silent in vanilla).
71+
void PatchMusicBoxVolume()
72+
{
73+
const BYTE Hotel1FSoundDataSearchBytes[]{ 0x00, 0x40, 0x83, 0xC6, 0x00, 0x40, 0xB5, 0x46, 0x00, 0x00, 0x48, 0x42 };
74+
const DWORD Hotel1FSoundDataAddr = SearchAndGetAddresses(0x008B3E20, 0x008B7A10, 0x008B6A10, Hotel1FSoundDataSearchBytes, sizeof(Hotel1FSoundDataSearchBytes), -0x50, __FUNCTION__);
75+
76+
const BYTE Hotel2FSoundDataSearchBytes[]{ 0x00, 0xC4, 0x6A, 0xC7, 0x00, 0x68, 0xBF, 0x47, 0x00, 0x00, 0x48, 0x42 };
77+
const DWORD Hotel2FSoundDataAddr = SearchAndGetAddresses(0x008B44A0, 0x008B8090, 0x008B7090, Hotel2FSoundDataSearchBytes, sizeof(Hotel2FSoundDataSearchBytes), 0x70, __FUNCTION__);
78+
79+
const BYTE Hotel2FStageSearchBytes[]{ 0x64, 0x68, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x74 };
80+
const DWORD Hotel2FStageAddr = SearchAndGetAddresses(0x008CA414, 0x008CE0E4, 0x008CD0E4, Hotel2FStageSearchBytes, sizeof(Hotel2FStageSearchBytes), -0x44, __FUNCTION__);
81+
82+
const BYTE BgmChangeSearchBytes[]{ 0x83, 0xC1, 0xFE, 0x83, 0xF9, 0x38 };
83+
const DWORD BgmChangeAddr = SearchAndGetAddresses(0x0051601C, 0x0051634C, 0x00515C6C, BgmChangeSearchBytes, sizeof(BgmChangeSearchBytes), 0x00, __FUNCTION__);
84+
85+
const BYTE GameFlagSearchBytes[]{ 0x83, 0xFE, 0x01, 0x55, 0x57, 0xBD, 0x00, 0x01, 0x00, 0x00 };
86+
GameFlagAddr = (BYTE*)ReadSearchedAddresses(0x0048AA9E, 0x0048AD3E, 0x0048AF4E, GameFlagSearchBytes, sizeof(GameFlagSearchBytes), 0x24, __FUNCTION__);
87+
88+
if (!Hotel1FSoundDataAddr || !Hotel2FSoundDataAddr || !Hotel2FStageAddr || !BgmChangeAddr || !GameFlagAddr)
89+
{
90+
Logging::Log() << __FUNCTION__ << " Error: failed to find memory address!";
91+
return;
92+
}
93+
94+
BgmChangeReturnAddr = BgmChangeAddr + 0x06;
95+
shBgmCall = (void(*)(int))(BgmChangeAddr + 0x2B + *(DWORD*)(BgmChangeAddr + 0x27));
96+
97+
Logging::Log() << "Patching Music Box Volume...";
98+
99+
WriteJMPtoMemory((BYTE*)BgmChangeAddr, *BgmChangeASM, 0x06);
100+
101+
// Set custom BGM control function for Hotel 2F.
102+
int(*GetStageBgmBankAddr)(void) = GetStageBgmBank;
103+
UpdateMemoryAddress((void*)(Hotel2FStageAddr + 0x30), &GetStageBgmBankAddr, sizeof(&GetStageBgmBank));
104+
105+
// Update BGM sound regions in Hotel 1F.
106+
const DWORD ChannelNoBanks = 0x00;
107+
const DWORD ChannelBank4 = 0x00100000;
108+
for (int i = 6; i <= 11; ++i)
109+
{
110+
// Quieter music box in 1F hallway.
111+
UpdateMemoryAddress((void*)(Hotel1FSoundDataAddr + i * 0x40 + 0x34), &ChannelNoBanks, sizeof(DWORD));
112+
UpdateMemoryAddress((void*)(Hotel1FSoundDataAddr + i * 0x40 + 0x3C), &ChannelBank4, sizeof(DWORD));
113+
}
114+
for (int i = 12; i <= 27; ++i)
115+
{
116+
// No music box in rooms other than lobby and reception.
117+
if (i == 19 || i == 20) continue;
118+
UpdateMemoryAddress((void*)(Hotel1FSoundDataAddr + i * 0x40 + 0x34), &ChannelNoBanks, sizeof(DWORD));
119+
}
120+
// No music box outside of known regions. This covers the 1F employee hallway since the sound regions
121+
// for this hallway are actually misplaced on top of a different room.
122+
UpdateMemoryAddress((void*)(Hotel1FSoundDataAddr + 0x34), &ChannelNoBanks, sizeof(DWORD));
123+
124+
// Update BGM sound regions in Hotel 2F.
125+
const DWORD EnableAreaFlag = 0x40000010;
126+
for (int i = 3; i <= 9; ++i)
127+
{
128+
// Quieter music box in 2F hallways connected to the lobby.
129+
UpdateMemoryAddress((void*)(Hotel2FSoundDataAddr + i * 0x40 + 0x20), &EnableAreaFlag, sizeof(DWORD));
130+
UpdateMemoryAddress((void*)(Hotel2FSoundDataAddr + i * 0x40 + 0x3C), &ChannelBank4, sizeof(DWORD));
131+
}
132+
// Quieter music box in cloak room.
133+
UpdateMemoryAddress((void*)(Hotel2FSoundDataAddr + 12 * 0x40 + 0x20), &EnableAreaFlag, sizeof(DWORD));
134+
UpdateMemoryAddress((void*)(Hotel2FSoundDataAddr + 12 * 0x40 + 0x3C), &ChannelBank4, sizeof(DWORD));
135+
}

Patches/Patches.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,7 @@ HRESULT PatchMasterVolumeSlider();
686686
void PatchMemoBrightnes();
687687
void PatchMenuSounds();
688688
void PatchMothDrawOrder();
689+
void PatchMusicBoxVolume();
689690
void PatchOldManCoinFix();
690691
void PatchObservationDeckFogFix();
691692
void PatchPauseScreen();

Patches/TeddyBearLookFix.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ void PatchTeddyBearLookFix()
6969
LookAtReturnAddr2 = LookAtInjectAddr + 0xA9;
7070

7171
constexpr BYTE GameFlagSearchBytes[]{ 0x83, 0xFE, 0x01, 0x55, 0x57, 0xBD, 0x00, 0x01, 0x00, 0x00 };
72-
GameFlagAddr = (BYTE*)ReadSearchedAddresses(0x0048AA9E, 0x0048AD3E, 0x0048AF4E, GameFlagSearchBytes, sizeof(LookAtSearchBytes), 0x24, __FUNCTION__);
73-
if (!LookAtInjectAddr)
72+
GameFlagAddr = (BYTE*)ReadSearchedAddresses(0x0048AA9E, 0x0048AD3E, 0x0048AF4E, GameFlagSearchBytes, sizeof(GameFlagSearchBytes), 0x24, __FUNCTION__);
73+
if (!GameFlagAddr)
7474
{
7575
Logging::Log() << __FUNCTION__ << " Error: failed to find memory address!";
7676
return;

dllmain.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,12 @@ void DelayedStart()
824824
{
825825
PatchLabyrinthElevatorVolumeFix();
826826
}
827+
828+
// Play a quieter music box track in certain rooms of the Lakeview Hotel.
829+
if (MusicBoxVolume)
830+
{
831+
PatchMusicBoxVolume();
832+
}
827833

828834
// Remove the "Now loading..." and "Press Return to continue." messages
829835
if (DisableLoadingPressReturnMessages)

sh2-enhce.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ copy /Y "$(ProjectDir)Resources\SH2EEsetup.exe" "$(TargetDir)" &gt;nul</Command>
228228
<ClCompile Include="Patches\MapTranscription.cpp" />
229229
<ClCompile Include="Patches\DelayedFadeIn.cpp" />
230230
<ClCompile Include="Patches\FmvSubtitles.cpp" />
231+
<ClCompile Include="Patches\MusicBoxVolume.cpp" />
231232
<ClCompile Include="Patches\OptionsMenuTweaks.cpp" />
232233
<ClCompile Include="Patches\PuzzleAlignmentFixes.cpp" />
233234
<ClCompile Include="Patches\MenuSounds.cpp" />

sh2-enhce.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,9 @@
479479
<ClCompile Include="Patches\LabyrinthElevatorVolumeFix.cpp">
480480
<Filter>Patches</Filter>
481481
</ClCompile>
482+
<ClCompile Include="Patches\MusicBoxVolume.cpp">
483+
<Filter>Patches</Filter>
484+
</ClCompile>
482485
</ItemGroup>
483486
<ItemGroup>
484487
<ClInclude Include="Common\Settings.h">

0 commit comments

Comments
 (0)