Skip to content

Commit 272ca4e

Browse files
authored
Fix initial state of the mannequin in Wood Side Apartments Room 205 (#1182)
1 parent b608f29 commit 272ca4e

File tree

5 files changed

+102
-0
lines changed

5 files changed

+102
-0
lines changed

Patches/Patches.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,7 @@ void PatchVHSAudio();
727727
void PatchWaterDrawOrderFix();
728728
void PatchWindowIcon();
729729
void PatchWindowTitle();
730+
void PatchWoodsideMannequinState();
730731
void PatchXInputVibration();
731732

732733
void FindGetModelID();

Patches/WoodsideMannequinState.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
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+
// Variables for ASM
24+
DWORD *FlashlightAcquiredAddr = nullptr;
25+
DWORD *SubCharStartAddr = nullptr;
26+
DWORD *MannequinFlagsAddr = nullptr;
27+
DWORD *jmpFixMannequinStateReturnAddr = 0;
28+
29+
// Scans the game object linked list for the mannequin in room 205 and correct its first state if it
30+
// has been mistakenly marked "dead" before the player picks up the flashlight. This code will only
31+
// be invoked when entering room 205 (0x17).
32+
__declspec(naked) void __stdcall FixMannequinStateASM()
33+
{
34+
__asm
35+
{
36+
mov eax, dword ptr ds : [FlashlightAcquiredAddr]
37+
test dword ptr ds : [eax], 0x40000
38+
jnz ExitASM
39+
mov eax, dword ptr ds : [SubCharStartAddr]
40+
41+
LoopStart:
42+
mov dx, word ptr ds : [eax + 0x10]
43+
cmp dx, 0x0201 // Kind == Mannequin?
44+
jnz LoopNext
45+
46+
mov edx, dword ptr ds : [eax + 0xEC] // edx := Enemy first status
47+
cmp edx, 0x05 // Status == Dead?
48+
jnz LoopNext
49+
mov dword ptr [eax + 0xEC], 0x09 // Status := Dormant (on ground)
50+
51+
LoopNext:
52+
mov eax, dword ptr [eax + 0x194]
53+
test eax, eax
54+
jnz LoopStart
55+
56+
pop esi
57+
ret
58+
59+
ExitASM:
60+
mov eax, dword ptr ds : [MannequinFlagsAddr]
61+
test dword ptr ds : [eax], 0x02000000
62+
jmp jmpFixMannequinStateReturnAddr
63+
}
64+
}
65+
66+
// Fixes the state of the mannequin in Woodside Apartments room 205 before picking up the flashlight.
67+
void PatchWoodsideMannequinState()
68+
{
69+
constexpr BYTE FlashlightAcquiredSearchBytes[]{ 0x8D, 0x50, 0x1C, 0x8B, 0x0A, 0x89, 0x0D };
70+
FlashlightAcquiredAddr = (DWORD*)ReadSearchedAddresses(0x0045507D, 0x004552DD, 0x004552DD, FlashlightAcquiredSearchBytes, sizeof(FlashlightAcquiredSearchBytes), 0x56, __FUNCTION__);
71+
72+
constexpr BYTE SubCharStartSearchBytes[]{ 0x57, 0x33, 0xC0, 0xB9, 0x64, 0x16, 0x00, 0x00 };
73+
SubCharStartAddr = (DWORD*)ReadSearchedAddresses(0x00538050, 0x00538380, 0x00537CA0, SubCharStartSearchBytes, sizeof(SubCharStartSearchBytes), 0x09, __FUNCTION__);
74+
75+
constexpr BYTE MannequinFlagsSearchBytes[]{ 0x8D, 0x54, 0x24, 0x2C, 0x5B, 0x52 };
76+
MannequinFlagsAddr = (DWORD*)ReadSearchedAddresses(0x0059BC29, 0x0059C4D9, 0x000059BDF9, MannequinFlagsSearchBytes, sizeof(MannequinFlagsSearchBytes), 0x08, __FUNCTION__);
77+
78+
constexpr BYTE FixMannequinStateSearchBytes[]{ 0xBE, 0x20, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x80 };
79+
const DWORD FixMannequinStateAddr = SearchAndGetAddresses(0x0059BA35, 0x0059C2E5, 0x0059BC05, FixMannequinStateSearchBytes, sizeof(FixMannequinStateSearchBytes), -0x11, __FUNCTION__);
80+
81+
if (!FlashlightAcquiredAddr || !SubCharStartAddr || !MannequinFlagsAddr || !FixMannequinStateAddr)
82+
{
83+
Logging::Log() << __FUNCTION__ << " Error: failed to find memory address!";
84+
return;
85+
}
86+
87+
jmpFixMannequinStateReturnAddr = (DWORD*)(FixMannequinStateAddr + 0x0A);
88+
89+
Logging::Log() << "Patching Woodside Room 205 Mannequin State Fix...";
90+
WriteJMPtoMemory((BYTE*)FixMannequinStateAddr, *FixMannequinStateASM, 0x0A);
91+
}

dllmain.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,12 @@ void DelayedStart()
825825
PatchLabyrinthElevatorVolumeFix();
826826
}
827827

828+
// Fix Mannequin state in Woodside Apartments room 205
829+
if (WoodsideRoom205Fix)
830+
{
831+
PatchWoodsideMannequinState();
832+
}
833+
828834
// Play a quieter music box track in certain rooms of the Lakeview Hotel.
829835
if (MusicBoxVolume)
830836
{

sh2-enhce.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@ copy /Y "$(ProjectDir)Resources\SH2EEsetup.exe" "$(TargetDir)" &gt;nul</Command>
304304
<ClCompile Include="Patches\VHSAudio.cpp" />
305305
<ClCompile Include="Patches\WaterDrawOrderFix.cpp" />
306306
<ClCompile Include="Patches\WaterEnhancement.cpp" />
307+
<ClCompile Include="Patches\WoodsideMannequinState.cpp" />
307308
<ClCompile Include="WidescreenFixesPack\WidescreenFixesPack.cpp" />
308309
<ClCompile Include="Wrappers\d3d8to9.cpp" />
309310
<ClCompile Include="Wrappers\d3d8\d3d8wrapper.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\WoodsideMannequinState.cpp">
483+
<Filter>Patches</Filter>
484+
</ClCompile>
482485
<ClCompile Include="Patches\MusicBoxVolume.cpp">
483486
<Filter>Patches</Filter>
484487
</ClCompile>

0 commit comments

Comments
 (0)