Skip to content

Commit 055f8f1

Browse files
committed
Add Blt Listener
1 parent cb117c8 commit 055f8f1

File tree

11 files changed

+207
-2
lines changed

11 files changed

+207
-2
lines changed

Examples/HelloWorld/HelloWorld/S4ModApi.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,8 @@ typedef HRESULT(FAR S4HCALL* LPS4MOUSECALLBACK)(DWORD dwMouseButton, INT iX, INT
440440
typedef HRESULT(FAR S4HCALL* LPS4SETTLERSENDCALLBACK)(DWORD dwPosition, S4_MOVEMENT_ENUM dwCommand, LPVOID lpReserved);
441441
typedef HRESULT(FAR S4HCALL* LPS4TICKCALLBACK)(DWORD dwTick, BOOL bHasEvent, BOOL bIsDelayed);
442442
typedef HRESULT(FAR S4HCALL* LPS4LUAOPENCALLBACK)(VOID);
443+
typedef BOOL (FAR S4HCALL* LPS4BLTCALLBACK)(DWORD _0, DWORD _1, DWORD _2, DWORD _3, DWORD _4, DWORD _5, DWORD _6, DWORD _7, DWORD _8, BOOL discard, DWORD caller);
444+
443445

444446

445447
HRESULT __declspec(nothrow) S4HCALL S4CreateInterface(CONST GUID FAR* lpGUID, LPSETTLERS4API FAR* lplpS4H);
@@ -471,6 +473,7 @@ DECLARE_INTERFACE_(ISettlers4Api, IUnknown) {
471473
STDMETHOD_(S4HOOK, AddSettlerSendListener)(THIS_ LPS4SETTLERSENDCALLBACK) PURE;
472474
STDMETHOD_(S4HOOK, AddTickListener)(THIS_ LPS4TICKCALLBACK) PURE;
473475
STDMETHOD_(S4HOOK, AddLuaOpenListener)(THIS_ LPS4LUAOPENCALLBACK) PURE;
476+
STDMETHOD_(S4HOOK, AddBltListener)(THIS_ LPS4BLTCALLBACK) PURE;
474477

475478

476479
/** Misc helper functions **/

Examples/LuaExample/LuaExample/S4ModApi.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,8 @@ typedef HRESULT(FAR S4HCALL* LPS4MOUSECALLBACK)(DWORD dwMouseButton, INT iX, INT
440440
typedef HRESULT(FAR S4HCALL* LPS4SETTLERSENDCALLBACK)(DWORD dwPosition, S4_MOVEMENT_ENUM dwCommand, LPVOID lpReserved);
441441
typedef HRESULT(FAR S4HCALL* LPS4TICKCALLBACK)(DWORD dwTick, BOOL bHasEvent, BOOL bIsDelayed);
442442
typedef HRESULT(FAR S4HCALL* LPS4LUAOPENCALLBACK)(VOID);
443+
typedef BOOL (FAR S4HCALL* LPS4BLTCALLBACK)(DWORD _0, DWORD _1, DWORD _2, DWORD _3, DWORD _4, DWORD _5, DWORD _6, DWORD _7, DWORD _8, BOOL discard, DWORD caller);
444+
443445

444446

445447
HRESULT __declspec(nothrow) S4HCALL S4CreateInterface(CONST GUID FAR* lpGUID, LPSETTLERS4API FAR* lplpS4H);
@@ -471,6 +473,7 @@ DECLARE_INTERFACE_(ISettlers4Api, IUnknown) {
471473
STDMETHOD_(S4HOOK, AddSettlerSendListener)(THIS_ LPS4SETTLERSENDCALLBACK) PURE;
472474
STDMETHOD_(S4HOOK, AddTickListener)(THIS_ LPS4TICKCALLBACK) PURE;
473475
STDMETHOD_(S4HOOK, AddLuaOpenListener)(THIS_ LPS4LUAOPENCALLBACK) PURE;
476+
STDMETHOD_(S4HOOK, AddBltListener)(THIS_ LPS4BLTCALLBACK) PURE;
474477

475478

476479
/** Misc helper functions **/

S4ModApi/CBltHook.cpp

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
///////////////////////////////////////////////////////////////////////////////
2+
// GNU Lesser General Public License v3 (LGPL v3)
3+
//
4+
// Copyright (c) 2020 nyfrk <nyfrk@gmx.net>
5+
//
6+
// This file is part of S4ModApi.
7+
//
8+
// S4ModApi is free software: you can redistribute it and/or modify
9+
// it under the terms of the GNU General Public License as published by
10+
// the Free Software Foundation, either version 3 of the License, or
11+
// (at your option) any later version.
12+
//
13+
// S4ModApi is distributed in the hope that it will be useful,
14+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
// GNU General Public License for more details.
17+
//
18+
// You should have received a copy of the GNU General Public License
19+
// along with S4ModApi. If not, see <https://www.gnu.org/licenses/lgpl-3.0>.
20+
///////////////////////////////////////////////////////////////////////////////
21+
22+
#include "globals.h" // g_isGE, hProcess
23+
#include "hlib.h" // JmpPatch
24+
#include "patterns.h"
25+
26+
#include "CBltHook.h"
27+
28+
static hlib::CallPatch OnBltHook;
29+
30+
BOOL __stdcall CBltHook::OnBlt(DWORD caller, DWORD ecx, DWORD edx, DWORD _0, DWORD _1, DWORD _2, DWORD _3, DWORD _4, DWORD _5, DWORD _6) {
31+
//TRACE; // we do not log this as it will be a mayor performance hit
32+
mutex.lock();
33+
auto observers = GetInstance().observers; // obtain a copy since the callbacks may modify the vector
34+
mutex.unlock();
35+
BOOL discard = false;
36+
for (auto& observer : observers) {
37+
discard |= ((LPS4BLTCALLBACK)observer.callback)(ecx, edx, _0, _1, _2, _3, _4, _5, _6, discard, caller);
38+
}
39+
return discard;
40+
}
41+
42+
static void __declspec(naked) __onBlt() {
43+
__asm {
44+
push edx
45+
push ecx
46+
47+
sub esp, 16
48+
movdqu[esp], xmm0
49+
sub esp, 16
50+
movdqu[esp], xmm1
51+
sub esp, 16
52+
movdqu[esp], xmm2
53+
sub esp, 16
54+
movdqu[esp], xmm3
55+
sub esp, 16
56+
movdqu[esp], xmm4
57+
sub esp, 16
58+
movdqu[esp], xmm5
59+
sub esp, 16
60+
movdqu[esp], xmm6
61+
sub esp, 16
62+
movdqu[esp], xmm7
63+
sub esp, 128
64+
fsave [esp]
65+
66+
push [esp + 296]
67+
push [esp + 296]
68+
push [esp + 296]
69+
push [esp + 296]
70+
push [esp + 296]
71+
push [esp + 296]
72+
push [esp + 296]
73+
push edx
74+
push ecx
75+
push [esp + 304]
76+
call CBltHook::OnBlt
77+
78+
frstor [esp]
79+
add esp, 128
80+
movdqu xmm7, [esp]
81+
add esp, 16
82+
movdqu xmm6, [esp]
83+
add esp, 16
84+
movdqu xmm5, [esp]
85+
add esp, 16
86+
movdqu xmm4, [esp]
87+
add esp, 16
88+
movdqu xmm3, [esp]
89+
add esp, 16
90+
movdqu xmm2, [esp]
91+
add esp, 16
92+
movdqu xmm1, [esp]
93+
add esp, 16
94+
movdqu xmm0, [esp]
95+
add esp, 16
96+
97+
test eax, eax
98+
99+
pop ecx
100+
pop edx
101+
pop eax
102+
jnz lbl_skip_original
103+
104+
// not skip original blt function
105+
106+
inc eax
107+
push ebp // repair replaced instructions
108+
mov ebp, esp
109+
push eax // must push here since the next replaced instruction will overwrite eax
110+
mov eax, [ebp+8]
111+
112+
lbl_skip_original:
113+
ret
114+
}
115+
}
116+
117+
CBltHook& CBltHook::GetInstance() {
118+
static CBltHook inst;
119+
return inst;
120+
}
121+
122+
bool CBltHook::Init() {
123+
TRACE;
124+
DWORD addr = g_Patterns.OnBltHook;
125+
if (!addr) return false;
126+
127+
OnBltHook = hlib::CallPatch(addr, (DWORD)__onBlt);
128+
129+
return true;
130+
}
131+
132+
void CBltHook::Patch() {
133+
TRACE;
134+
OnBltHook.patch();
135+
}
136+
137+
void CBltHook::Unpatch() {
138+
TRACE;
139+
OnBltHook.unpatch();
140+
}
141+
142+
CBltHook::CBltHook() { TRACE; }

S4ModApi/CBltHook.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
///////////////////////////////////////////////////////////////////////////////
2+
// GNU Lesser General Public License v3 (LGPL v3)
3+
//
4+
// Copyright (c) 2020 nyfrk <nyfrk@gmx.net>
5+
//
6+
// This file is part of S4ModApi.
7+
//
8+
// S4ModApi is free software: you can redistribute it and/or modify
9+
// it under the terms of the GNU General Public License as published by
10+
// the Free Software Foundation, either version 3 of the License, or
11+
// (at your option) any later version.
12+
//
13+
// S4ModApi is distributed in the hope that it will be useful,
14+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
// GNU General Public License for more details.
17+
//
18+
// You should have received a copy of the GNU General Public License
19+
// along with S4ModApi. If not, see <https://www.gnu.org/licenses/lgpl-3.0>.
20+
///////////////////////////////////////////////////////////////////////////////
21+
22+
#pragma once
23+
24+
#include "CHook.h"
25+
26+
class CBltHook : public CHook {
27+
public:
28+
static CBltHook& GetInstance();
29+
30+
protected:
31+
virtual bool Init();
32+
virtual void Patch();
33+
virtual void Unpatch();
34+
35+
private:
36+
CBltHook();
37+
static BOOL __stdcall CBltHook::OnBlt(DWORD caller, DWORD ecx, DWORD edx, DWORD _0, DWORD _1, DWORD _2, DWORD _3, DWORD _4, DWORD _5, DWORD _6);
38+
};
39+

S4ModApi/CS4Listeners.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "CSettlerSendHook.h"
2828
#include "CTickHook.h"
2929
#include "CLuaOpenHook.h"
30+
#include "CBltHook.h"
3031

3132
extern "C" {
3233

@@ -70,4 +71,9 @@ extern "C" {
7071
return CLuaOpenHook::GetInstance().AddListener(cb);
7172
}
7273

74+
S4HOOK CSettlers4Api::AddBltListener(LPS4BLTCALLBACK cb) {
75+
TRACE;
76+
return CBltHook::GetInstance().AddListener(cb);
77+
}
78+
7379
}

S4ModApi/CSettlers4Api.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ struct CSettlers4Api : public ISettlers4Api {
4444
STDMETHOD_(S4HOOK, AddSettlerSendListener)(THIS_ LPS4SETTLERSENDCALLBACK); // defined in CS4Listeners.cpp
4545
STDMETHOD_(S4HOOK, AddTickListener)(THIS_ LPS4TICKCALLBACK); // defined in CS4Listeners.cpp
4646
STDMETHOD_(S4HOOK, AddLuaOpenListener)(THIS_ LPS4LUAOPENCALLBACK); // defined in CS4Listeners.cpp
47+
STDMETHOD_(S4HOOK, AddBltListener)(THIS_ LPS4BLTCALLBACK); // defined in CS4Listeners.cpp
4748

4849
STDMETHOD(GetMD5OfModule)(THIS_ HMODULE module, LPSTR out, SIZE_T sz); // defined in CS4Misc.cpp
4950
STDMETHOD_(BOOL, IsEdition)(THIS_ S4_EDITION_ENUM edition); // defined in CS4Misc.cpp

S4ModApi/S4ModApi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ typedef HRESULT(FAR S4HCALL* LPS4MOUSECALLBACK)(DWORD dwMouseButton, INT iX, INT
440440
typedef HRESULT(FAR S4HCALL* LPS4SETTLERSENDCALLBACK)(DWORD dwPosition, S4_MOVEMENT_ENUM dwCommand, LPVOID lpReserved);
441441
typedef HRESULT(FAR S4HCALL* LPS4TICKCALLBACK)(DWORD dwTick, BOOL bHasEvent, BOOL bIsDelayed);
442442
typedef HRESULT(FAR S4HCALL* LPS4LUAOPENCALLBACK)(VOID);
443+
typedef BOOL (FAR S4HCALL* LPS4BLTCALLBACK)(DWORD _0, DWORD _1, DWORD _2, DWORD _3, DWORD _4, DWORD _5, DWORD _6, DWORD _7, DWORD _8, BOOL discard, DWORD caller);
443444

444445

445446
HRESULT __declspec(nothrow) S4HCALL S4CreateInterface(CONST GUID FAR* lpGUID, LPSETTLERS4API FAR* lplpS4H);
@@ -471,6 +472,7 @@ DECLARE_INTERFACE_(ISettlers4Api, IUnknown) {
471472
STDMETHOD_(S4HOOK, AddSettlerSendListener)(THIS_ LPS4SETTLERSENDCALLBACK) PURE;
472473
STDMETHOD_(S4HOOK, AddTickListener)(THIS_ LPS4TICKCALLBACK) PURE;
473474
STDMETHOD_(S4HOOK, AddLuaOpenListener)(THIS_ LPS4LUAOPENCALLBACK) PURE;
475+
STDMETHOD_(S4HOOK, AddBltListener)(THIS_ LPS4BLTCALLBACK) PURE;
474476

475477

476478
/** Misc helper functions **/

S4ModApi/S4ModApi.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@
158158
</ResourceCompile>
159159
</ItemDefinitionGroup>
160160
<ItemGroup>
161+
<ClCompile Include="CBltHook.cpp" />
161162
<ClCompile Include="CCustomUi.cpp" />
162163
<ClCompile Include="CFrameHook.cpp" />
163164
<ClCompile Include="CHook.cpp" />
@@ -204,6 +205,7 @@
204205
<ClCompile Include="CUpdate.cpp" />
205206
</ItemGroup>
206207
<ItemGroup>
208+
<ClInclude Include="CBltHook.h" />
207209
<ClInclude Include="CCustomUi.h" />
208210
<ClInclude Include="CDialog.h" />
209211
<ClInclude Include="CFrameHook.h" />

S4ModApi/S4ModApi.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@
192192
<ClCompile Include="CLuaOpenHook.cpp">
193193
<Filter>Quelldateien\Hooks</Filter>
194194
</ClCompile>
195+
<ClCompile Include="CBltHook.cpp">
196+
<Filter>Quelldateien\Hooks</Filter>
197+
</ClCompile>
195198
</ItemGroup>
196199
<ItemGroup>
197200
<ClInclude Include="resource.h">
@@ -266,6 +269,9 @@
266269
<ClInclude Include="CLuaOpenHook.h">
267270
<Filter>Headerdateien\Hooks</Filter>
268271
</ClInclude>
272+
<ClInclude Include="CBltHook.h">
273+
<Filter>Headerdateien\Hooks</Filter>
274+
</ClInclude>
269275
</ItemGroup>
270276
<ItemGroup>
271277
<ResourceCompile Include="S4ModApi.rc">

S4ModApi/patterns.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ void Patterns::Scan() {
7878
SCAN_HE(Lua, S4_Main, "75 0D 50 E8 ? ? ? ? 83 C4 04 33 F6 EB 1B 50 6A 00 E8 ? ? ? ? 8B F0 83 C4 08 85 F6 75 0A B9 ? ? ? ? E8 ? ? ? ? 8B 15");
7979
SCAN_HE(ShowTextMessage, S4_Main, "55 8B EC 53 56 57 6A 24 8B F2 8B F9");
8080
SCAN_HE(OnLuaOpenHook, S4_Main, "89 5F 0C 89 5F 10 89 5F 14 89 5F 18 89 5F 04 89 5F 08 89 9F ? ? ? ? 89 3D ? ? ? ? E8"); // +30
81-
81+
SCAN_HE(OnBltHook, S4_Main, "55 8B EC 8B 45 08 A3 ? ? ? ? 89 15 ? ? ? ? 8B 15 ? ? ? ? 89 0D ? ? ? ? 8B 4D 20 53 56 8B 34 82 8B 45 0C");
8282
}
8383
}
8484

0 commit comments

Comments
 (0)