Skip to content

Commit

Permalink
Add GuiBltListener
Browse files Browse the repository at this point in the history
  • Loading branch information
nyfrk committed Feb 21, 2021
1 parent 676e4ba commit d6aa610
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 0 deletions.
12 changes: 12 additions & 0 deletions Examples/HelloWorld/HelloWorld/S4ModApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,16 @@ typedef struct S4BltParams {
HDC destinationDc;
} *LPS4BLTPARAMS;

typedef struct S4GuiBltParams {
DWORD id;
LPVOID dstSurface;
LPRECT dstRect;
LPVOID srcSurface;
LPRECT srcRect;
DWORD ddbltFlags;
LPVOID ddbltfx;
} *LPS4GUIBLTPARAMS;

/** Callback types **/
typedef HRESULT(FAR S4HCALL* LPS4FRAMECALLBACK)(LPDIRECTDRAWSURFACE7 lpSurface, INT32 iPillarboxWidth, LPVOID lpReserved);
typedef HRESULT(FAR S4HCALL* LPS4MAPINITCALLBACK)(LPVOID lpReserved0, LPVOID lpReserved1);
Expand All @@ -691,6 +701,7 @@ typedef HRESULT(FAR S4HCALL* LPS4SETTLERSENDCALLBACK)(DWORD dwPosition, S4_MOVEM
typedef HRESULT(FAR S4HCALL* LPS4TICKCALLBACK)(DWORD dwTick, BOOL bHasEvent, BOOL bIsDelayed);
typedef HRESULT(FAR S4HCALL* LPS4LUAOPENCALLBACK)(VOID);
typedef BOOL (FAR S4HCALL* LPS4BLTCALLBACK)(LPS4BLTPARAMS params, BOOL discard);
typedef BOOL (FAR S4HCALL* LPS4GUIBLTCALLBACK)(LPS4GUIBLTPARAMS params, BOOL discard);
typedef HRESULT(FAR S4HCALL* LPS4ENTITYCALLBACK)(WORD entity, S4_ENTITY_CAUSE cause); // called when an entity is spawned or destructed // todo: implement me


Expand Down Expand Up @@ -725,6 +736,7 @@ DECLARE_INTERFACE_(ISettlers4Api, IUnknown) {
STDMETHOD_(S4HOOK, AddLuaOpenListener)(THIS_ LPS4LUAOPENCALLBACK) PURE;
STDMETHOD_(S4HOOK, AddBltListener)(THIS_ LPS4BLTCALLBACK) PURE;
STDMETHOD_(S4HOOK, AddEntityListener)(THIS_ LPS4ENTITYCALLBACK) PURE;
STDMETHOD_(S4HOOK, AddGuiBltListener)(THIS_ LPS4GUIBLTCALLBACK) PURE;

/** Misc helper functions **/
STDMETHOD(GetMD5OfModule)(THIS_ HMODULE module, LPSTR out, SIZE_T sz) PURE;
Expand Down
12 changes: 12 additions & 0 deletions Examples/LuaExample/LuaExample/S4ModApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,16 @@ typedef struct S4BltParams {
HDC destinationDc;
} *LPS4BLTPARAMS;

typedef struct S4GuiBltParams {
DWORD id;
LPVOID dstSurface;
LPRECT dstRect;
LPVOID srcSurface;
LPRECT srcRect;
DWORD ddbltFlags;
LPVOID ddbltfx;
} *LPS4GUIBLTPARAMS;

/** Callback types **/
typedef HRESULT(FAR S4HCALL* LPS4FRAMECALLBACK)(LPDIRECTDRAWSURFACE7 lpSurface, INT32 iPillarboxWidth, LPVOID lpReserved);
typedef HRESULT(FAR S4HCALL* LPS4MAPINITCALLBACK)(LPVOID lpReserved0, LPVOID lpReserved1);
Expand All @@ -691,6 +701,7 @@ typedef HRESULT(FAR S4HCALL* LPS4SETTLERSENDCALLBACK)(DWORD dwPosition, S4_MOVEM
typedef HRESULT(FAR S4HCALL* LPS4TICKCALLBACK)(DWORD dwTick, BOOL bHasEvent, BOOL bIsDelayed);
typedef HRESULT(FAR S4HCALL* LPS4LUAOPENCALLBACK)(VOID);
typedef BOOL (FAR S4HCALL* LPS4BLTCALLBACK)(LPS4BLTPARAMS params, BOOL discard);
typedef BOOL (FAR S4HCALL* LPS4GUIBLTCALLBACK)(LPS4GUIBLTPARAMS params, BOOL discard);
typedef HRESULT(FAR S4HCALL* LPS4ENTITYCALLBACK)(WORD entity, S4_ENTITY_CAUSE cause); // called when an entity is spawned or destructed // todo: implement me


Expand Down Expand Up @@ -725,6 +736,7 @@ DECLARE_INTERFACE_(ISettlers4Api, IUnknown) {
STDMETHOD_(S4HOOK, AddLuaOpenListener)(THIS_ LPS4LUAOPENCALLBACK) PURE;
STDMETHOD_(S4HOOK, AddBltListener)(THIS_ LPS4BLTCALLBACK) PURE;
STDMETHOD_(S4HOOK, AddEntityListener)(THIS_ LPS4ENTITYCALLBACK) PURE;
STDMETHOD_(S4HOOK, AddGuiBltListener)(THIS_ LPS4GUIBLTCALLBACK) PURE;

/** Misc helper functions **/
STDMETHOD(GetMD5OfModule)(THIS_ HMODULE module, LPSTR out, SIZE_T sz) PURE;
Expand Down
171 changes: 171 additions & 0 deletions S4ModApi/CGuiBltHook.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
///////////////////////////////////////////////////////////////////////////////
// GNU Lesser General Public License v3 (LGPL v3)
//
// Copyright (c) 2020 nyfrk <nyfrk@gmx.net>
//
// This file is part of S4ModApi.
//
// S4ModApi is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// S4ModApi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with S4ModApi. If not, see <https://www.gnu.org/licenses/lgpl-3.0>.
///////////////////////////////////////////////////////////////////////////////

#include "globals.h" // g_isGE, hProcess
#include "hlib.h" // JmpPatch
#include "patterns.h"

#include "CGuiBltHook.h"

static hlib::CallPatch OnComposeBltHook, OnSettlerIdHook;

BOOL __stdcall CGuiBltHook::OnBlt(DWORD id, LPVOID dstSurface, LPRECT dstRect, LPVOID srcSurface, LPRECT srcRect, DWORD ddbltFlags, LPVOID ddbltfx) {
//TRACE; // we do not log this as it will be a mayor performance hit
mutex.lock();
auto observers = GetInstance().observers; // obtain a copy since the callbacks may modify the vector
mutex.unlock();
BOOL discard = false;
S4GuiBltParams params;

params.id = id / 4; // id goes from 0x130 (incl) to 0x167 (excl)
params.dstSurface = dstSurface;
params.dstRect = dstRect;
params.srcSurface = srcSurface;
params.srcRect = srcRect;
params.ddbltFlags = ddbltFlags;
params.ddbltfx = ddbltfx;

for (auto& observer : observers) {
discard |= ((LPS4GUIBLTCALLBACK)observer.callback)(&params, discard);
}

return discard;
}

static void __declspec(naked) __onBlt() {
__asm {
sub esp, 16
movdqu[esp], xmm0
sub esp, 16
movdqu[esp], xmm1
sub esp, 16
movdqu[esp], xmm2
sub esp, 16
movdqu[esp], xmm3
sub esp, 16
movdqu[esp], xmm4
sub esp, 16
movdqu[esp], xmm5
sub esp, 16
movdqu[esp], xmm6
sub esp, 16
movdqu[esp], xmm7
sub esp, 128
fsave[esp]

push ecx
push edx
push[esp + 256 + 4 + 20]
push[esp + 256 + 4 + 20]
push[esp + 256 + 4 + 20]
push[esp + 256 + 4 + 20]
push[esp + 256 + 4 + 20]
push ecx
push edi
call CGuiBltHook::OnBlt
pop edx
pop ecx

frstor[esp]
add esp, 128
movdqu xmm7, [esp]
add esp, 16
movdqu xmm6, [esp]
add esp, 16
movdqu xmm5, [esp]
add esp, 16
movdqu xmm4, [esp]
add esp, 16
movdqu xmm3, [esp]
add esp, 16
movdqu xmm2, [esp]
add esp, 16
movdqu xmm1, [esp]
add esp, 16
movdqu xmm0, [esp]
add esp, 16

test al, al
pushf
xor eax, eax
popf
jnz lbl_skip_original
push[esp + 20]
push[esp + 20]
push[esp + 20]
push[esp + 20]
push[esp + 20]
call [esi + 0x18]

lbl_skip_original:

pop esi // ret addr
add esp, 20 // clean the stack

push esi
test eax, eax
ret
}
}

CGuiBltHook& CGuiBltHook::GetInstance() {
static CGuiBltHook inst;
return inst;
}

bool CGuiBltHook::Init() {
TRACE;
/*
S4_Main.exe+2647C6 - 8B 45 FC - mov eax,[ebp-04]
S4_Main.exe+2647C9 - 8B 15 08875401 - mov edx,[S4_Main.exe+1058708] { (04860720) }
S4_Main.exe+2647CF - 8D 80 D8456E01 - lea eax,[eax+S4_Main.exe+11F45D8]
S4_Main.exe+2647D5 - 8B 4A 5C - mov ecx,[edx+5C]
S4_Main.exe+2647D8 - 50 - push eax
S4_Main.exe+2647D9 - 8B 45 FC - mov eax,[ebp-04]
S4_Main.exe+2647DC - FF 34 17 - push [edi+edx]
S4_Main.exe+2647DF - 8B 31 - mov esi,[ecx]
S4_Main.exe+2647E1 - 8D 80 B8466E01 - lea eax,[eax+S4_Main.exe+11F46B8]
S4_Main.exe+2647E7 - 50 - push eax
S4_Main.exe+2647E8 - FF 56 18 - call dword ptr [esi+18] <--- we hook here, 5 arguments + ecx
S4_Main.exe+2647EB - 85 C0 - test eax,eax
*/


DWORD addr = S4_Main != 0 ? S4_Main + 0x2647E8 : 0;
if (!addr) return false;

OnComposeBltHook = hlib::CallPatch(addr, (DWORD)__onBlt);

return true;
}

void CGuiBltHook::Patch() {
TRACE;
OnComposeBltHook.patch();
}

void CGuiBltHook::Unpatch() {
TRACE;
OnComposeBltHook.unpatch();
}

CGuiBltHook::CGuiBltHook() { TRACE; }
39 changes: 39 additions & 0 deletions S4ModApi/CGuiBltHook.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
///////////////////////////////////////////////////////////////////////////////
// GNU Lesser General Public License v3 (LGPL v3)
//
// Copyright (c) 2020 nyfrk <nyfrk@gmx.net>
//
// This file is part of S4ModApi.
//
// S4ModApi is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// S4ModApi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with S4ModApi. If not, see <https://www.gnu.org/licenses/lgpl-3.0>.
///////////////////////////////////////////////////////////////////////////////

#pragma once

#include "CHook.h"

class CGuiBltHook : public CHook {
public:
static CGuiBltHook& GetInstance();

protected:
virtual bool Init();
virtual void Patch();
virtual void Unpatch();

private:
CGuiBltHook();
static BOOL __stdcall OnBlt(DWORD id, LPVOID dstSurface, LPRECT dstRect, LPVOID srcSurface, LPRECT srcRect, DWORD ddbltFlags, LPVOID ddbltfx);
};

6 changes: 6 additions & 0 deletions S4ModApi/CS4Listeners.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "CLuaOpenHook.h"
#include "CBltHook.h"
#include "CEntityHook.h"
#include "CGuiBltHook.h"

extern "C" {

Expand Down Expand Up @@ -82,4 +83,9 @@ extern "C" {
return CEntityHook::GetInstance().AddListener(cb);
}

S4HOOK CSettlers4Api::AddGuiBltListener(LPS4GUIBLTCALLBACK cb) {
TRACE;
return CGuiBltHook::GetInstance().AddListener(cb);
}

}
1 change: 1 addition & 0 deletions S4ModApi/CSettlers4Api.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ struct CSettlers4Api : public ISettlers4Api {
STDMETHOD_(S4HOOK, AddLuaOpenListener)(THIS_ LPS4LUAOPENCALLBACK); // defined in CS4Listeners.cpp
STDMETHOD_(S4HOOK, AddBltListener)(THIS_ LPS4BLTCALLBACK); // defined in CS4Listeners.cpp
STDMETHOD_(S4HOOK, AddEntityListener)(THIS_ LPS4ENTITYCALLBACK); // defined in CS4Listeners.cpp
STDMETHOD_(S4HOOK, AddGuiBltListener)(THIS_ LPS4GUIBLTCALLBACK); // defined in CS4Listeners.cpp

STDMETHOD(GetMD5OfModule)(THIS_ HMODULE module, LPSTR out, SIZE_T sz); // defined in CS4Misc.cpp
STDMETHOD_(BOOL, IsEdition)(THIS_ S4_EDITION_ENUM edition); // defined in CS4Misc.cpp
Expand Down
12 changes: 12 additions & 0 deletions S4ModApi/S4ModApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,16 @@ typedef struct S4BltParams {
HDC destinationDc;
} *LPS4BLTPARAMS;

typedef struct S4GuiBltParams {
DWORD id;
LPVOID dstSurface;
LPRECT dstRect;
LPVOID srcSurface;
LPRECT srcRect;
DWORD ddbltFlags;
LPVOID ddbltfx;
} *LPS4GUIBLTPARAMS;

/** Callback types **/
typedef HRESULT(FAR S4HCALL* LPS4FRAMECALLBACK)(LPDIRECTDRAWSURFACE7 lpSurface, INT32 iPillarboxWidth, LPVOID lpReserved);
typedef HRESULT(FAR S4HCALL* LPS4MAPINITCALLBACK)(LPVOID lpReserved0, LPVOID lpReserved1);
Expand All @@ -691,6 +701,7 @@ typedef HRESULT(FAR S4HCALL* LPS4SETTLERSENDCALLBACK)(DWORD dwPosition, S4_MOVEM
typedef HRESULT(FAR S4HCALL* LPS4TICKCALLBACK)(DWORD dwTick, BOOL bHasEvent, BOOL bIsDelayed);
typedef HRESULT(FAR S4HCALL* LPS4LUAOPENCALLBACK)(VOID);
typedef BOOL (FAR S4HCALL* LPS4BLTCALLBACK)(LPS4BLTPARAMS params, BOOL discard);
typedef BOOL (FAR S4HCALL* LPS4GUIBLTCALLBACK)(LPS4GUIBLTPARAMS params, BOOL discard);
typedef HRESULT(FAR S4HCALL* LPS4ENTITYCALLBACK)(WORD entity, S4_ENTITY_CAUSE cause); // called when an entity is spawned or destructed // todo: implement me


Expand Down Expand Up @@ -725,6 +736,7 @@ DECLARE_INTERFACE_(ISettlers4Api, IUnknown) {
STDMETHOD_(S4HOOK, AddLuaOpenListener)(THIS_ LPS4LUAOPENCALLBACK) PURE;
STDMETHOD_(S4HOOK, AddBltListener)(THIS_ LPS4BLTCALLBACK) PURE;
STDMETHOD_(S4HOOK, AddEntityListener)(THIS_ LPS4ENTITYCALLBACK) PURE;
STDMETHOD_(S4HOOK, AddGuiBltListener)(THIS_ LPS4GUIBLTCALLBACK) PURE;

/** Misc helper functions **/
STDMETHOD(GetMD5OfModule)(THIS_ HMODULE module, LPSTR out, SIZE_T sz) PURE;
Expand Down
2 changes: 2 additions & 0 deletions S4ModApi/S4ModApi.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="CBltHook.cpp" />
<ClCompile Include="CGuiBltHook.cpp" />
<ClCompile Include="CCustomUi.cpp" />
<ClCompile Include="CEntityHook.cpp" />
<ClCompile Include="CFrameHook.cpp" />
Expand Down Expand Up @@ -209,6 +210,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="CBltHook.h" />
<ClInclude Include="CGuiBltHook.h" />
<ClInclude Include="CCustomUi.h" />
<ClInclude Include="CDialog.h" />
<ClInclude Include="CEntityHook.h" />
Expand Down
6 changes: 6 additions & 0 deletions S4ModApi/S4ModApi.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@
<ClCompile Include="CEntityHook.cpp">
<Filter>Quelldateien\Hooks</Filter>
</ClCompile>
<ClCompile Include="CGuiBltHook.cpp">
<Filter>Quelldateien\Hooks</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h">
Expand Down Expand Up @@ -281,6 +284,9 @@
<ClInclude Include="CEntityHook.h">
<Filter>Headerdateien\Hooks</Filter>
</ClInclude>
<ClInclude Include="CGuiBltHook.h">
<Filter>Headerdateien\Hooks</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="S4ModApi.rc">
Expand Down

0 comments on commit d6aa610

Please sign in to comment.