diff --git a/src/Syroot.Worms.sln b/src/Syroot.Worms.sln
index d707d86..ad68862 100644
--- a/src/Syroot.Worms.sln
+++ b/src/Syroot.Worms.sln
@@ -49,13 +49,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = " Solution Items", " Solut
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Syroot.Worms.Worms2.GameServer", "tool\Syroot.Worms.Worms2.GameServer\Syroot.Worms.Worms2.GameServer.csproj", "{13ABF717-5809-441D-A5D8-66E1EE75A390}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fkNetcode", "tool\fkNetcode\fkNetcode.vcxproj", "{C4138811-7CFA-4826-A3DD-AF2B618EAFC1}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Module Projects", "Module Projects", "{2A8C6AAA-BA1F-4FB6-A598-114930217B6C}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FrontendKitWS", "tool\FrontendKitWS\FrontendKitWS.vcxproj", "{E391EA12-B929-466C-932F-DEF72B8CEB5D}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WormKitTools", "module\WormKitTools\WormKitTools.vcxproj", "{068A8647-0A66-4E39-983B-43ACEAC5C937}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wkUnlimiter", "tool\wkUnlimiter\wkUnlimiter.vcxproj", "{CDED4B7C-91DF-45D3-9704-DB8750BDAF5B}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FrontendKitWS", "module\FrontendKitWS\FrontendKitWS.vcxproj", "{E391EA12-B929-466C-932F-DEF72B8CEB5D}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WormKitTools", "tool\WormKitTools\FrontendKitLib.vcxproj", "{068A8647-0A66-4E39-983B-43ACEAC5C937}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fkDesPatch", "module\fkDesPatch\fkDesPatch.vcxproj", "{6B4D57EA-4642-440A-AB62-2E011D7B64E1}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fkNetcode", "module\fkNetcode\fkNetcode.vcxproj", "{C4138811-7CFA-4826-A3DD-AF2B618EAFC1}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wkUnlimiter", "module\wkUnlimiter\wkUnlimiter.vcxproj", "{CDED4B7C-91DF-45D3-9704-DB8750BDAF5B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -131,22 +135,26 @@ Global
{13ABF717-5809-441D-A5D8-66E1EE75A390}.Debug|Any CPU.Build.0 = Debug|Any CPU
{13ABF717-5809-441D-A5D8-66E1EE75A390}.Release|Any CPU.ActiveCfg = Release|Any CPU
{13ABF717-5809-441D-A5D8-66E1EE75A390}.Release|Any CPU.Build.0 = Release|Any CPU
- {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Debug|Any CPU.ActiveCfg = Debug|Win32
- {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Debug|Any CPU.Build.0 = Debug|Win32
- {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Release|Any CPU.ActiveCfg = Release|Win32
- {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Release|Any CPU.Build.0 = Release|Win32
- {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Debug|Any CPU.ActiveCfg = Debug|Win32
- {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Debug|Any CPU.Build.0 = Debug|Win32
- {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Release|Any CPU.ActiveCfg = Release|Win32
- {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Release|Any CPU.Build.0 = Release|Win32
- {CDED4B7C-91DF-45D3-9704-DB8750BDAF5B}.Debug|Any CPU.ActiveCfg = Debug|Win32
- {CDED4B7C-91DF-45D3-9704-DB8750BDAF5B}.Debug|Any CPU.Build.0 = Debug|Win32
- {CDED4B7C-91DF-45D3-9704-DB8750BDAF5B}.Release|Any CPU.ActiveCfg = Release|Win32
- {CDED4B7C-91DF-45D3-9704-DB8750BDAF5B}.Release|Any CPU.Build.0 = Release|Win32
{068A8647-0A66-4E39-983B-43ACEAC5C937}.Debug|Any CPU.ActiveCfg = Debug|Win32
{068A8647-0A66-4E39-983B-43ACEAC5C937}.Debug|Any CPU.Build.0 = Debug|Win32
{068A8647-0A66-4E39-983B-43ACEAC5C937}.Release|Any CPU.ActiveCfg = Release|Win32
{068A8647-0A66-4E39-983B-43ACEAC5C937}.Release|Any CPU.Build.0 = Release|Win32
+ {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Debug|Any CPU.Build.0 = Debug|Win32
+ {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Release|Any CPU.ActiveCfg = Release|Win32
+ {E391EA12-B929-466C-932F-DEF72B8CEB5D}.Release|Any CPU.Build.0 = Release|Win32
+ {6B4D57EA-4642-440A-AB62-2E011D7B64E1}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {6B4D57EA-4642-440A-AB62-2E011D7B64E1}.Debug|Any CPU.Build.0 = Debug|Win32
+ {6B4D57EA-4642-440A-AB62-2E011D7B64E1}.Release|Any CPU.ActiveCfg = Release|Win32
+ {6B4D57EA-4642-440A-AB62-2E011D7B64E1}.Release|Any CPU.Build.0 = Release|Win32
+ {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Debug|Any CPU.Build.0 = Debug|Win32
+ {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Release|Any CPU.ActiveCfg = Release|Win32
+ {C4138811-7CFA-4826-A3DD-AF2B618EAFC1}.Release|Any CPU.Build.0 = Release|Win32
+ {CDED4B7C-91DF-45D3-9704-DB8750BDAF5B}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {CDED4B7C-91DF-45D3-9704-DB8750BDAF5B}.Debug|Any CPU.Build.0 = Debug|Win32
+ {CDED4B7C-91DF-45D3-9704-DB8750BDAF5B}.Release|Any CPU.ActiveCfg = Release|Win32
+ {CDED4B7C-91DF-45D3-9704-DB8750BDAF5B}.Release|Any CPU.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -169,10 +177,11 @@ Global
{212F8090-9775-4098-BD44-9ABC01FBE553} = {99E56312-A064-4AD3-8443-0B56A5F76E6B}
{1FAB6B9F-2585-46DC-81C0-579DC808C389} = {0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}
{13ABF717-5809-441D-A5D8-66E1EE75A390} = {0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}
- {C4138811-7CFA-4826-A3DD-AF2B618EAFC1} = {0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}
- {E391EA12-B929-466C-932F-DEF72B8CEB5D} = {0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}
- {CDED4B7C-91DF-45D3-9704-DB8750BDAF5B} = {0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}
- {068A8647-0A66-4E39-983B-43ACEAC5C937} = {0B9B0B74-3EB1-46A4-BCCC-F2D6AE59A9EE}
+ {068A8647-0A66-4E39-983B-43ACEAC5C937} = {2A8C6AAA-BA1F-4FB6-A598-114930217B6C}
+ {E391EA12-B929-466C-932F-DEF72B8CEB5D} = {2A8C6AAA-BA1F-4FB6-A598-114930217B6C}
+ {6B4D57EA-4642-440A-AB62-2E011D7B64E1} = {2A8C6AAA-BA1F-4FB6-A598-114930217B6C}
+ {C4138811-7CFA-4826-A3DD-AF2B618EAFC1} = {2A8C6AAA-BA1F-4FB6-A598-114930217B6C}
+ {CDED4B7C-91DF-45D3-9704-DB8750BDAF5B} = {2A8C6AAA-BA1F-4FB6-A598-114930217B6C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1CD4EDE2-A5FB-4A58-A850-3506AB7E7B69}
diff --git a/src/tool/FrontendKitWS/FrontendKitWS.rc b/src/module/FrontendKitWS/FrontendKitWS.rc
similarity index 100%
rename from src/tool/FrontendKitWS/FrontendKitWS.rc
rename to src/module/FrontendKitWS/FrontendKitWS.rc
diff --git a/src/tool/FrontendKitWS/FrontendKitWS.vcxproj b/src/module/FrontendKitWS/FrontendKitWS.vcxproj
similarity index 100%
rename from src/tool/FrontendKitWS/FrontendKitWS.vcxproj
rename to src/module/FrontendKitWS/FrontendKitWS.vcxproj
diff --git a/src/tool/FrontendKitWS/fk.h b/src/module/FrontendKitWS/fk.h
similarity index 100%
rename from src/tool/FrontendKitWS/fk.h
rename to src/module/FrontendKitWS/fk.h
diff --git a/src/tool/FrontendKitWS/main.cpp b/src/module/FrontendKitWS/main.cpp
similarity index 100%
rename from src/tool/FrontendKitWS/main.cpp
rename to src/module/FrontendKitWS/main.cpp
diff --git a/src/tool/FrontendKitWS/main.def b/src/module/FrontendKitWS/main.def
similarity index 100%
rename from src/tool/FrontendKitWS/main.def
rename to src/module/FrontendKitWS/main.def
diff --git a/src/tool/FrontendKitWS/resource.h b/src/module/FrontendKitWS/resource.h
similarity index 100%
rename from src/tool/FrontendKitWS/resource.h
rename to src/module/FrontendKitWS/resource.h
diff --git a/src/tool/WormKitTools/FrontendKitLib.vcxproj b/src/module/WormKitTools/WormKitTools.vcxproj
similarity index 95%
rename from src/tool/WormKitTools/FrontendKitLib.vcxproj
rename to src/module/WormKitTools/WormKitTools.vcxproj
index 81f1a0f..941ebec 100644
--- a/src/tool/WormKitTools/FrontendKitLib.vcxproj
+++ b/src/module/WormKitTools/WormKitTools.vcxproj
@@ -93,7 +93,7 @@
-
+
@@ -103,13 +103,14 @@
-
+
+
diff --git a/src/tool/WormKitTools/FrontendKitLib.vcxproj.filters b/src/module/WormKitTools/WormKitTools.vcxproj.filters
similarity index 89%
rename from src/tool/WormKitTools/FrontendKitLib.vcxproj.filters
rename to src/module/WormKitTools/WormKitTools.vcxproj.filters
index bcecdc6..6ef6fd8 100644
--- a/src/tool/WormKitTools/FrontendKitLib.vcxproj.filters
+++ b/src/module/WormKitTools/WormKitTools.vcxproj.filters
@@ -18,9 +18,6 @@
Source Files
-
- Source Files
-
Source Files
@@ -30,14 +27,14 @@
Source Files
+
+ Source Files
+
Header Files
-
- Header Files
-
Header Files
@@ -47,10 +44,16 @@
Header Files
+
+ Header Files
+
Header Files
+
+ Header Files
+
\ No newline at end of file
diff --git a/src/module/WormKitTools/include/wkExe.h b/src/module/WormKitTools/include/wkExe.h
new file mode 100644
index 0000000..6d9cf32
--- /dev/null
+++ b/src/module/WormKitTools/include/wkExe.h
@@ -0,0 +1,88 @@
+#pragma once
+#include
+#include
+#include
+#include "wkPatch.h"
+
+namespace wk
+{
+ enum JumpType
+ {
+ JT_JMP, // jmp (0xE9)
+ JT_CALL, // call (0xE8)
+ JT_FARJMP, // farjump (0xEA)
+ JT_FARCALL, // farcall (0x9A)
+ JT_PUSHRET, // pushret
+ };
+
+ struct Exe
+ {
+ public:
+ // ---- FIELDS -------------------------------------------------------------------------------------------------
+
+ HANDLE Handle;
+ PIMAGE_DOS_HEADER DosHeader;
+ PIMAGE_NT_HEADERS NtHeader;
+ PIMAGE_FILE_HEADER FileHeader;
+ PIMAGE_OPTIONAL_HEADER OptHeader;
+
+ // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
+
+ Exe(HMODULE hModule = NULL);
+
+ // ---- METHODS ------------------------------------------------------------------------------------------------
+
+ ///
+ /// Returns the offset of the first match of the given signature. It must take the form "12 FF ?? EB 34", where
+ /// two question marks represent a wildcard.
+ ///
+ /// The signature to find.
+ /// The offset of the first match of the signature.
+ ULONG_PTR find(std::string signature);
+
+ ///
+ /// Returns the offset of the first match of the given signature. It is an array of bytes, where all values
+ /// being negative or bigger than 0xFF represent a wildcard.
+ ///
+ /// The signature to find.
+ /// The offset of the first match of the signature.
+ ULONG_PTR find(int16_t signature[], size_t signatureSize); // any non-uint8_t value is a wildcard
+
+ ///
+ /// Writes the given value to the specified offset.
+ ///
+ /// The type of the value to write.
+ /// The relative address at which to write the value.
+ /// The value to write.
+ template void set(ULONG_PTR offset, T value);
+
+ ///
+ /// Replaces the given import with the specified hook, which must have the same signature.
+ ///
+ /// The imported method to replace.
+ /// The method to replace the import with.
+ void setImp(LPVOID import, LPVOID hook);
+
+ ///
+ /// Writes a jump to the given callee at the specified offset.
+ ///
+ /// The relative address at which to write the value.
+ /// The number of bytes overwritten for the jump opcode.
+ /// The called method.
+ /// The type of the jump to insert.
+ void setJmp(ULONG_PTR offset, SIZE_T size, LPVOID callee, DWORD jumpType);
+
+ ///
+ /// Nops out the given number of bytes at the specified offset.
+ ///
+ /// The relative address at which to nop out code.
+ /// The number of bytes to nop out.
+ void setNop(ULONG_PTR offset, SIZE_T size);
+
+ private:
+ LPVOID getAddress(ULONG_PTR offset);
+ PIMAGE_IMPORT_DESCRIPTOR getImports();
+ };
+}
+
+#include "wkExe.inl"
\ No newline at end of file
diff --git a/src/module/WormKitTools/include/wkExe.inl b/src/module/WormKitTools/include/wkExe.inl
new file mode 100644
index 0000000..4f1602e
--- /dev/null
+++ b/src/module/WormKitTools/include/wkExe.inl
@@ -0,0 +1,9 @@
+namespace wk
+{
+ template
+ void Exe::set(ULONG_PTR offset, T newValue)
+ {
+ Patch patch(getAddress(offset), sizeof(T));
+ patch.write(newValue);
+ }
+}
\ No newline at end of file
diff --git a/src/tool/WormKitTools/include/wkConfig.h b/src/module/WormKitTools/include/wkIni.h
similarity index 88%
rename from src/tool/WormKitTools/include/wkConfig.h
rename to src/module/WormKitTools/include/wkIni.h
index d754698..cf8f184 100644
--- a/src/tool/WormKitTools/include/wkConfig.h
+++ b/src/module/WormKitTools/include/wkIni.h
@@ -3,10 +3,10 @@
namespace wk
{
- class Config
+ class Ini
{
public:
- Config(LPCSTR fileName);
+ Ini(LPCSTR fileName);
void get(LPCSTR category, LPCSTR key, BOOL& result, UINT fallback) const;
void get(LPCSTR category, LPCSTR key, UINT& result, UINT fallback) const;
diff --git a/src/module/WormKitTools/include/wkPatch.h b/src/module/WormKitTools/include/wkPatch.h
new file mode 100644
index 0000000..4b7c2b5
--- /dev/null
+++ b/src/module/WormKitTools/include/wkPatch.h
@@ -0,0 +1,31 @@
+#pragma once
+#include
+
+namespace wk
+{
+ struct Patch
+ {
+ public:
+ // ---- FIELDS -------------------------------------------------------------------------------------------------
+
+ ULONG_PTR position;
+
+ // ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
+
+ Patch(LPVOID address, SIZE_T size);
+ ~Patch();
+
+ // ---- METHODS ------------------------------------------------------------------------------------------------
+
+ void close() const;
+ template void write(const T& value);
+
+ private:
+ // ---- FIELDS -------------------------------------------------------------------------------------------------
+ LPBYTE _address;
+ SIZE_T _size;
+ DWORD _oldProtect;
+ };
+}
+
+#include "wkPatch.inl"
diff --git a/src/tool/WormKitTools/include/wkPatch.inl b/src/module/WormKitTools/include/wkPatch.inl
similarity index 100%
rename from src/tool/WormKitTools/include/wkPatch.inl
rename to src/module/WormKitTools/include/wkPatch.inl
diff --git a/src/tool/WormKitTools/include/wkUtils.h b/src/module/WormKitTools/include/wkUtils.h
similarity index 59%
rename from src/tool/WormKitTools/include/wkUtils.h
rename to src/module/WormKitTools/include/wkUtils.h
index c9d3397..0529e1c 100644
--- a/src/tool/WormKitTools/include/wkUtils.h
+++ b/src/module/WormKitTools/include/wkUtils.h
@@ -14,21 +14,28 @@ namespace wk
GAMEID_W2_1_05 = GAMEID_W2 | 0x010500,
GAMEID_W2_1_05_BR = GAMEID_W2_1_05 | 0x10, // Worms2 1.05 Br
GAMEID_W2_1_05_EN = GAMEID_W2_1_05 | 0x20, // Worms2 1.05 Du, En, Fr, It, Po, Sp, Sw
- GAMEID_W2_1_05_GE = GAMEID_W2_1_05 | 0x30, // Worms2 1.05
- GAMEID_W2_1_05_NA = GAMEID_W2_1_05 | 0x40, // Worms2 1.05
- GAMEID_W2_1_05_SA = GAMEID_W2_1_05 | 0x50, // Worms2 1.05
+ GAMEID_W2_1_05_GE = GAMEID_W2_1_05 | 0x30, // Worms2 1.05 De
+ GAMEID_W2_1_05_NA = GAMEID_W2_1_05 | 0x40, // Worms2 1.05 NA
+ GAMEID_W2_1_05_SA = GAMEID_W2_1_05 | 0x50, // Worms2 1.05 SA
GAMEID_W2_1_07 = GAMEID_W2 | 0x010700,
GAMEID_W2_1_07_TRY = GAMEID_W2_1_07 | 0x60, // Worms2 1.07 Trymedia
+ GAMEID_W2_LAST = GAMEID_W2_1_07_TRY,
GAMEID_WA = 0x30000000,
+ GAMEID_WA_3_6_31 = GAMEID_WA | 0x030630, // Worms Armageddon 3.6.31
+ GAMEID_WA_3_7_2_1 = GAMEID_WA | 0x030721, // Worms Armageddon 3.7.2.1
GAMEID_WA_3_8 = GAMEID_WA | 0x030800,
GAMEID_WA_3_8_CD = GAMEID_WA_3_8 | 0x10, // Worms Armageddon 3.8 CD
+ GAMEID_WA_LAST = GAMEID_WA_3_8_CD,
GAMEID_WWP = 0x40000000,
+ GAMEID_WWP_LAST = GAMEID_WWP,
GAMEID_OW = 0x50000000,
+ GAMEID_OW_LAST = GAMEID_OW,
GAMEID_WWPA = 0x60000000,
+ GAMEID_WWPA_LAST = GAMEID_WWPA,
};
int getGameID(DWORD timeDateStamp);
diff --git a/src/tool/WormKitTools/src/pch.cpp b/src/module/WormKitTools/src/pch.cpp
similarity index 100%
rename from src/tool/WormKitTools/src/pch.cpp
rename to src/module/WormKitTools/src/pch.cpp
diff --git a/src/tool/WormKitTools/src/pch.h b/src/module/WormKitTools/src/pch.h
similarity index 100%
rename from src/tool/WormKitTools/src/pch.h
rename to src/module/WormKitTools/src/pch.h
diff --git a/src/module/WormKitTools/src/wkExe.cpp b/src/module/WormKitTools/src/wkExe.cpp
new file mode 100644
index 0000000..b62320d
--- /dev/null
+++ b/src/module/WormKitTools/src/wkExe.cpp
@@ -0,0 +1,160 @@
+#include "wkExe.h"
+#include
+#include
+#include
+#include
+
+namespace wk
+{
+ // ---- CONSTRUCTORS & DESTRUCTOR ----------------------------------------------------------------------------------
+
+ Exe::Exe(HMODULE hModule)
+ {
+ Handle = hModule == NULL ? GetModuleHandleA(NULL) : hModule;
+ DosHeader = (PIMAGE_DOS_HEADER)Handle;
+ NtHeader = (PIMAGE_NT_HEADERS)((DWORD)DosHeader + DosHeader->e_lfanew);
+ FileHeader = (PIMAGE_FILE_HEADER)&NtHeader->FileHeader;
+ OptHeader = (PIMAGE_OPTIONAL_HEADER)&NtHeader->OptionalHeader;
+ }
+
+ // ---- METHODS (PUBLIC) -------------------------------------------------------------------------------------------
+
+ ULONG_PTR Exe::find(std::string signature)
+ {
+ std::istringstream iss(signature);
+ std::istream_iterator begin(iss), end;
+ std::vector tokens(begin, end);
+
+ std::vector sig;
+ for (auto& token : tokens)
+ sig.push_back(token == "??" ? -1 : std::stoi(token, 0, 16));
+
+ return find(&sig[0], sig.size());
+ }
+
+ ULONG_PTR Exe::find(int16_t signature[], size_t signatureSize)
+ {
+ PIMAGE_SECTION_HEADER sections = IMAGE_FIRST_SECTION(NtHeader);
+ for (int index = 0; index < FileHeader->NumberOfSections; index++)
+ {
+ if (sections[index].Characteristics != (IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ))
+ continue;
+ LPBYTE code = (LPBYTE)(ULONG_PTR)Handle + sections[index].VirtualAddress;
+ LPBYTE last = &code[sections[index].SizeOfRawData - signatureSize];
+ for (; code < last; code++)
+ {
+ bool found = true;
+ for (size_t i = 0; i < signatureSize; i++)
+ {
+ if (signature[i] < 0x00 || signature[i] > 0xFF || code[i] == (BYTE)signature[i])
+ {
+ continue;
+ }
+ else
+ {
+ found = false;
+ break;
+ }
+ }
+ if (found)
+ return (ULONG_PTR)code - (ULONG_PTR)Handle;
+ }
+ }
+ throw std::exception("Could not find signature.");
+ }
+
+ void Exe::setImp(LPVOID import, LPVOID hook)
+ {
+ bool success = false;
+ PIMAGE_IMPORT_DESCRIPTOR imports = getImports();
+ if (!imports)
+ throw std::exception("Import patching failed, import table not found.");
+
+ while (imports->Characteristics)
+ {
+ PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)Handle + imports->OriginalFirstThunk);
+ PIMAGE_THUNK_DATA table = (PIMAGE_THUNK_DATA)((ULONG_PTR)Handle + imports->FirstThunk);
+ while (thunk->u1.Ordinal)
+ {
+ if (table->u1.Function == (ULONG_PTR)import)
+ {
+ Patch patch(&table->u1.Function, sizeof(ULONG_PTR));
+ patch.write(hook);
+ success = true;
+ }
+ thunk++;
+ table++;
+ }
+ imports++;
+ }
+
+ if (!success)
+ throw std::exception("Import patching failed, import not found.");
+ }
+
+ void Exe::setJmp(ULONG_PTR offset, SIZE_T size, LPVOID callee, DWORD jumpType)
+ {
+ Patch patch(getAddress(offset), size);
+
+ if (size >= 5 && offset)
+ {
+ BYTE opSize, opCode;
+ switch (jumpType)
+ {
+ case JT_PUSHRET: opSize = 6; opCode = 0x68; break;
+ case JT_FARJMP: opSize = 7; opCode = 0xEA; break;
+ case JT_FARCALL: opSize = 7; opCode = 0x9A; break;
+ case JT_CALL: opSize = 5; opCode = 0xE8; break;
+ default: opSize = 5; opCode = 0xE9; break;
+ }
+
+ if (size < opSize)
+ throw std::exception("Not enough space to patch opcode.");
+
+ patch.write(opCode);
+ switch (opSize)
+ {
+ case 7:
+ patch.write((ULONG)callee);
+ patch.write(0x23);
+ break;
+ case 6:
+ patch.write((ULONG)callee);
+ patch.write(0xC3);
+ break;
+ default:
+ patch.write((ULONG)callee - (ULONG_PTR)offset - 5);
+ break;
+ }
+ for (DWORD i = opSize; i < size; i++)
+ patch.write((uint8_t)0x90);
+ }
+ }
+
+ void Exe::setNop(ULONG_PTR offset, SIZE_T size)
+ {
+ Patch patch(getAddress(offset), size);
+ while (size--)
+ patch.write((uint8_t)0x90);
+ }
+
+ // ---- METHODS (PRIVATE) ------------------------------------------------------------------------------------------
+
+ LPVOID Exe::getAddress(ULONG_PTR offset)
+ {
+ return (LPVOID)((ULONG_PTR)Handle + offset);
+ }
+
+ PIMAGE_IMPORT_DESCRIPTOR Exe::getImports()
+ {
+ if ((FileHeader->SizeOfOptionalHeader
+ >= FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT + 1]))
+ && OptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
+ && OptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size)
+ {
+ return (PIMAGE_IMPORT_DESCRIPTOR)((ULONG_PTR)Handle
+ + OptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
+ }
+ return NULL;
+ }
+}
diff --git a/src/tool/WormKitTools/src/wkConfig.cpp b/src/module/WormKitTools/src/wkIni.cpp
similarity index 56%
rename from src/tool/WormKitTools/src/wkConfig.cpp
rename to src/module/WormKitTools/src/wkIni.cpp
index b09888d..26b3388 100644
--- a/src/tool/WormKitTools/src/wkConfig.cpp
+++ b/src/module/WormKitTools/src/wkIni.cpp
@@ -1,38 +1,38 @@
-#include "wkConfig.h"
+#include "wkIni.h"
#include
namespace wk
{
- Config::Config(LPCSTR fileName)
+ Ini::Ini(LPCSTR fileName)
{
GetModuleFileName(NULL, _filePath, MAX_PATH);
char* sepIdx = strrchr(_filePath, '\\') + 1;
strcpy_s(sepIdx, MAX_PATH - (int)(sepIdx - _filePath), fileName);
}
- void Config::get(LPCSTR category, LPCSTR key, BOOL& result, UINT fallback) const
+ void Ini::get(LPCSTR category, LPCSTR key, BOOL& result, UINT fallback) const
{
result = GetPrivateProfileInt(category, key, fallback, _filePath);
}
- void Config::get(LPCSTR category, LPCSTR key, UINT& result, UINT fallback) const
+ void Ini::get(LPCSTR category, LPCSTR key, UINT& result, UINT fallback) const
{
result = GetPrivateProfileInt(category, key, fallback, _filePath);
}
- void Config::get(LPCSTR category, LPCSTR key, LPSTR result, INT resultLength, LPCSTR fallback) const
+ void Ini::get(LPCSTR category, LPCSTR key, LPSTR result, INT resultLength, LPCSTR fallback) const
{
GetPrivateProfileString(category, key, fallback, result, resultLength, _filePath);
}
- void Config::set(LPCSTR category, LPCSTR key, UINT value) const
+ void Ini::set(LPCSTR category, LPCSTR key, UINT value) const
{
CHAR buffer[32];
sprintf_s(buffer, "%d", value);
WritePrivateProfileString(category, key, buffer, _filePath);
}
- void Config::set(LPCSTR category, LPCSTR key, LPCSTR value) const
+ void Ini::set(LPCSTR category, LPCSTR key, LPCSTR value) const
{
WritePrivateProfileString(category, key, value, _filePath);
}
diff --git a/src/module/WormKitTools/src/wkPatch.cpp b/src/module/WormKitTools/src/wkPatch.cpp
new file mode 100644
index 0000000..4aff3fd
--- /dev/null
+++ b/src/module/WormKitTools/src/wkPatch.cpp
@@ -0,0 +1,32 @@
+#include "wkPatch.h"
+#include
+
+namespace wk
+{
+ // ---- CONSTRUCTORS & DESTRUCTOR ----------------------------------------------------------------------------------
+
+ Patch::Patch(LPVOID address, SIZE_T size)
+ : _address((LPBYTE)address)
+ , _size(size)
+ , position(0)
+ {
+ if (!_address || !_size)
+ throw std::invalid_argument("Address and size must not be 0.");
+ if (!VirtualProtect(_address, _size, PAGE_EXECUTE_READWRITE, &_oldProtect))
+ throw std::exception("VirtualProtect failed, call GetLastError for more info.");
+ }
+
+ Patch::~Patch()
+ {
+ close();
+ }
+
+ // ---- METHODS (PUBLIC) -------------------------------------------------------------------------------------------
+
+ void Patch::close() const
+ {
+ DWORD oldProtect;
+ if (!VirtualProtect(_address, _size, _oldProtect, &oldProtect))
+ throw std::exception("VirtualProtect failed, call GetLastError for more info.");
+ }
+};
diff --git a/src/tool/WormKitTools/src/wkUtils.cpp b/src/module/WormKitTools/src/wkUtils.cpp
similarity index 88%
rename from src/tool/WormKitTools/src/wkUtils.cpp
rename to src/module/WormKitTools/src/wkUtils.cpp
index 44036ee..5efd6cc 100644
--- a/src/tool/WormKitTools/src/wkUtils.cpp
+++ b/src/module/WormKitTools/src/wkUtils.cpp
@@ -14,6 +14,8 @@ namespace wk
case 0x3528DA98: return GAMEID_W2_1_05_NA;
case 0x3528DBDA: return GAMEID_W2_1_05_SA;
case 0x3587BE19: return GAMEID_W2_1_07_TRY;
+ case 0x4CE25091: return GAMEID_WA_3_6_31;
+ case 0x513D83BC: return GAMEID_WA_3_7_2_1;
case 0x5EF04515: return GAMEID_WA_3_8_CD;
default: return GAMEID_NONE;
}
diff --git a/src/module/fkDesPatch/fkDesPatch.vcxproj b/src/module/fkDesPatch/fkDesPatch.vcxproj
new file mode 100644
index 0000000..c1dc506
--- /dev/null
+++ b/src/module/fkDesPatch/fkDesPatch.vcxproj
@@ -0,0 +1,99 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ 16.0
+ Win32Proj
+ {6b4d57ea-4642-440a-ab62-2e011d7b64e1}
+ fkDesPatch
+ 10.0
+
+
+
+ DynamicLibrary
+ true
+ v142
+ MultiByte
+
+
+ DynamicLibrary
+ false
+ v142
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ bin\$(Configuration)\
+ obj\$(Configuration)\
+
+
+ false
+ bin\$(Configuration)\
+ obj\$(Configuration)\
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;FKDESPATCH_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ $(ProjectDir)..\WormKitTools\include\;%(AdditionalIncludeDirectories)
+
+
+ Windows
+ true
+ false
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;FKDESPATCH_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ $(ProjectDir)..\WormKitTools\include\;%(AdditionalIncludeDirectories)
+
+
+ Windows
+ true
+ true
+ true
+ false
+
+
+
+
+
+
+
+ {068a8647-0a66-4e39-983b-43aceac5c937}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/module/fkDesPatch/main.cpp b/src/module/fkDesPatch/main.cpp
new file mode 100644
index 0000000..038c848
--- /dev/null
+++ b/src/module/fkDesPatch/main.cpp
@@ -0,0 +1,84 @@
+#define WIN32_LEAN_AND_MEAN
+#include
+#include
+#include "wkExe.h"
+#include "wkIni.h"
+#include "wkUtils.h"
+
+// ---- Initialization ----
+
+BOOL iniAutoOssett;
+
+void init()
+{
+ wk::Ini ini("fkDesPatch.ini");
+
+ // Load INI settings.
+ ini.get("Frontend", "AutoOssett", iniAutoOssett, FALSE);
+
+ // Ensure INI file has been created with default setting.
+ ini.set("Frontend", "AutoOssett", iniAutoOssett);
+}
+
+// ---- Patch ----
+
+void patch(wk::Exe& exe, int gameVersion)
+{
+ if (gameVersion == wk::GAMEID_W2_1_07_TRY)
+ {
+
+ }
+ else
+ {
+ // getAddress file to code 0x400C02
+ if (iniAutoOssett)
+ exe.set(0x000446A2, (uint8_t)0xEB);
+ }
+}
+
+// ---- Main ----
+
+int getVersion(DWORD timeDateStamp)
+{
+ int id = wk::getGameID(timeDateStamp);
+ switch (id)
+ {
+ case wk::GAMEID_W2_1_05_BR:
+ case wk::GAMEID_W2_1_05_EN:
+ case wk::GAMEID_W2_1_05_GE:
+ case wk::GAMEID_W2_1_05_NA:
+ case wk::GAMEID_W2_1_05_SA:
+ case wk::GAMEID_W2_1_07_TRY:
+ return id;
+ default:
+ return 0;
+ }
+}
+
+BOOL WINAPI DllMain(HMODULE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ wk::Exe exe;
+ int version = getVersion(exe.FileHeader->TimeDateStamp);
+ if (version)
+ {
+ init();
+ patch(exe, version);
+ }
+ else
+ {
+ MessageBox(NULL, "fkDesPatch is incompatible with your game version. Please run the 1.05 patch or 1.07 "
+ "release of Worms 2. Otherwise, you can delete the module to remove this warning.", "fkDesPatch",
+ MB_ICONWARNING);
+ }
+ }
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
diff --git a/src/tool/fkNetcode/fkNetcode.rc b/src/module/fkNetcode/fkNetcode.rc
similarity index 100%
rename from src/tool/fkNetcode/fkNetcode.rc
rename to src/module/fkNetcode/fkNetcode.rc
diff --git a/src/tool/fkNetcode/fkNetcode.vcxproj b/src/module/fkNetcode/fkNetcode.vcxproj
similarity index 96%
rename from src/tool/fkNetcode/fkNetcode.vcxproj
rename to src/module/fkNetcode/fkNetcode.vcxproj
index 19ae316..792f9ae 100644
--- a/src/tool/fkNetcode/fkNetcode.vcxproj
+++ b/src/module/fkNetcode/fkNetcode.vcxproj
@@ -98,7 +98,7 @@
-
+
{068a8647-0a66-4e39-983b-43aceac5c937}
diff --git a/src/tool/fkNetcode/main.cpp b/src/module/fkNetcode/main.cpp
similarity index 67%
rename from src/tool/fkNetcode/main.cpp
rename to src/module/fkNetcode/main.cpp
index ecd949d..e5e004f 100644
--- a/src/tool/fkNetcode/main.cpp
+++ b/src/module/fkNetcode/main.cpp
@@ -2,36 +2,36 @@
#include
#include
#include
-#include "wkConfig.h"
+#include "wkIni.h"
#include "wkExe.h"
#include "wkPatch.h"
#include "wkUtils.h"
-// ---- Configuration ----
+// ---- Initialization ----
-CHAR cfgFallbackIP[16];
-CHAR cfgServiceUrl[MAX_PATH];
-BOOL cfgShowErrors;
+CHAR iniFallbackIP[16];
+CHAR iniServiceUrl[MAX_PATH];
+BOOL iniShowErrors;
-void configure()
+void init()
{
- wk::Config config("fkNetcode.ini");
+ wk::Ini ini("fkNetcode.ini");
// Load INI settings.
- config.get("AddressResolval", "FallbackIP", cfgFallbackIP, 16);
- config.get("AddressResolval", "ServiceUrl", cfgServiceUrl, MAX_PATH, "http://ip.syroot.com");
- config.get("AddressResolval", "ShowErrors", cfgShowErrors, TRUE);
+ ini.get("AddressResolval", "FallbackIP", iniFallbackIP, 16);
+ ini.get("AddressResolval", "ServiceUrl", iniServiceUrl, MAX_PATH, "http://ip.syroot.com");
+ ini.get("AddressResolval", "ShowErrors", iniShowErrors, TRUE);
// Ensure INI file has been created with default setting.
- config.set("AddressResolval", "FallbackIP", cfgFallbackIP);
- config.set("AddressResolval", "ServiceUrl", cfgServiceUrl);
- config.set("AddressResolval", "ShowErrors", cfgShowErrors);
+ ini.set("AddressResolval", "FallbackIP", iniFallbackIP);
+ ini.set("AddressResolval", "ServiceUrl", iniServiceUrl);
+ ini.set("AddressResolval", "ShowErrors", iniShowErrors);
// Validate fallback IP.
BYTE b;
- if (*cfgFallbackIP && sscanf_s(cfgFallbackIP, "%hhu.%hhu.%hhu.%hhu", &b, &b, &b, &b) != 4)
+ if (*iniFallbackIP && sscanf_s(iniFallbackIP, "%hhu.%hhu.%hhu.%hhu", &b, &b, &b, &b) != 4)
{
- *cfgFallbackIP = NULL;
+ *iniFallbackIP = NULL;
MessageBox(NULL, "Invalid fallback IP setting in fkNetcode.ini has been ignored.", "fkNetcode", MB_ICONWARNING);
}
}
@@ -50,14 +50,14 @@ bool resolveIPCached(LPSTR buffer)
bool resolveIPExternal(LPSTR buffer)
{
- if (!*cfgServiceUrl)
+ if (!*iniServiceUrl)
return false;
// Query a web service which replies with the IP in plain text.
HINTERNET hInternet = 0, hFile = 0;
if (hInternet = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0))
{
- if (hFile = InternetOpenUrl(hInternet, cfgServiceUrl, NULL, 0,
+ if (hFile = InternetOpenUrl(hInternet, iniServiceUrl, NULL, 0,
INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD, NULL))
{
DWORD responseLength = 0;
@@ -84,7 +84,7 @@ bool resolveIPExternal(LPSTR buffer)
DWORD error = GetLastError();
if (hFile) InternetCloseHandle(hFile);
if (hInternet) InternetCloseHandle(hInternet);
- if (error && cfgShowErrors)
+ if (error && iniShowErrors)
{
CHAR msg[512];
sprintf_s(msg, "Could not resolve your IP through the web service. %s", wk::getErrorMessage(error).c_str());
@@ -95,9 +95,9 @@ bool resolveIPExternal(LPSTR buffer)
bool resolveIPFallback(LPSTR buffer)
{
- if (!*cfgFallbackIP)
+ if (!*iniFallbackIP)
return false;
- lstrcpy(buffer, cfgFallbackIP);
+ lstrcpy(buffer, iniFallbackIP);
return true;
}
@@ -136,19 +136,19 @@ bool __stdcall patchResolveIP(LPSTR buffer, int bufferLength)
void patch(wk::Exe& exe, int gameVersion)
{
- wk::Patch::jump(exe.Offset(0x00001799), 5, &patchResolveIP, wk::IJ_JUMP); // replace IP resolve with web service
+ exe.setJmp(0x00001799, 5, &patchResolveIP, wk::JT_JMP); // replace IP resolve with web service
if (gameVersion == wk::GAMEID_W2_1_07_TRY)
{
- wk::Patch::nops(exe.Offset(0x00053B96), 5); // prevent overriding IP with user name
- wk::Patch::nops(exe.Offset(0x00054693), 5); // prevent overriding IP with NAT IP
- wk::Patch::nops(exe.Offset(0x00054635), 11); // useless sleep when connecting to server
+ exe.setNop(0x00053B96, 5); // prevent overriding IP with user name
+ exe.setNop(0x00054693, 5); // prevent overriding IP with NAT IP
+ exe.setNop(0x00054635, 11); // useless sleep when connecting to server
}
else
{
- wk::Patch::nops(exe.Offset(0x00053E96), 5); // prevent overriding IP with user name
- wk::Patch::nops(exe.Offset(0x00054935), 11); // useless sleep when connecting to server
- wk::Patch::nops(exe.Offset(0x00054993), 5); // prevent overriding IP with NAT IP
+ exe.setNop(0x00053E96, 5); // prevent overriding IP with user name
+ exe.setNop(0x00054935, 11); // useless sleep when connecting to server
+ exe.setNop(0x00054993, 5); // prevent overriding IP with NAT IP
}
}
@@ -181,7 +181,7 @@ BOOL WINAPI DllMain(HMODULE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
int version = getVersion(exe.FileHeader->TimeDateStamp);
if (version)
{
- configure();
+ init();
patch(exe, version);
}
else
diff --git a/src/tool/fkNetcode/resource.h b/src/module/fkNetcode/resource.h
similarity index 100%
rename from src/tool/fkNetcode/resource.h
rename to src/module/fkNetcode/resource.h
diff --git a/src/module/wkUnlimiter/main.cpp b/src/module/wkUnlimiter/main.cpp
new file mode 100644
index 0000000..dd41cf4
--- /dev/null
+++ b/src/module/wkUnlimiter/main.cpp
@@ -0,0 +1,132 @@
+#define WIN32_LEAN_AND_MEAN
+#include
+#include
+#include "wkConfig.h"
+#include "wkExe.h"
+#include "wkUtils.h"
+
+// ---- Initialization ----
+
+BOOL iniAllowMultiInstance;
+BOOL iniEnableAllControls;
+BOOL iniShowAllControls;
+BOOL iniUnlockCamera;
+BOOL iniUnlockCursor;
+
+void init(int gameID)
+{
+ wk::Ini ini("wkUnlimiter.ini");
+
+ // Load INI settings.
+ ini.get("Common", "AllowMultiInstance", iniAllowMultiInstance, TRUE);
+ ini.get("Frontend", "EnableAllControls", iniEnableAllControls, TRUE);
+ ini.get("Frontend", "ShowAllControls", iniShowAllControls, FALSE);
+ if (gameID == wk::GAMEID_WA_3_8_CD)
+ {
+ ini.get("Game", "UnlockCamera", iniUnlockCamera, TRUE);
+ ini.get("Game", "UnlockCursor", iniUnlockCursor, TRUE);
+ }
+
+ // Ensure INI file has been created with default setting.
+ ini.set("Common", "AllowMultiInstance", iniAllowMultiInstance);
+ ini.set("Frontend", "EnableAllControls", iniEnableAllControls);
+ ini.set("Frontend", "ShowAllControls", iniShowAllControls);
+ if (gameID == wk::GAMEID_WA_3_8_CD)
+ {
+ ini.set("Game", "UnlockCamera", iniUnlockCamera);
+ ini.set("Game", "UnlockCursor", iniUnlockCursor);
+ }
+}
+
+// ---- Patch ----
+
+HANDLE WINAPI Kernel32_CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount,
+ LONG lMaximumCount, LPCSTR lpName)
+{
+ HANDLE handle = CreateSemaphoreA(lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName);
+ SetLastError(ERROR_SUCCESS);
+ return handle;
+}
+
+void patch(wk::Exe& exe, int gameID)
+{
+ if (iniAllowMultiInstance)
+ {
+ // Requires WormKitDS as game loads modules after this
+ exe.setImp(CreateSemaphoreA, Kernel32_CreateSemaphoreA);
+ }
+ if (iniEnableAllControls)
+ {
+ // CWnd::EnableWindow(bEnable) -> CWnd::EnableWindow(TRUE)
+ exe.set(exe.find("C2 04 00 8B 49 50 8B 01 FF A0 A8") - 13, 0x9090016A);
+ }
+ if (iniShowAllControls)
+ {
+ // CWnd::ShowWindow(bShow) -> CWnd::ShowWindow(TRUE)
+ exe.set(exe.find("C2 04 00 8B 49 50 8B 01 FF A0 A0") - 13, 0x9090016A);
+ }
+ if (iniUnlockCamera)
+ {
+ exe.setNop(exe.find("89 13 EB 06 3B C7 7E 02"), 2); // X- axis
+ exe.setNop(exe.find("89 3B 8B 43 04 3B C1 7D 09 5F 5E"), 2); // X+ axis
+ exe.setNop(exe.find("89 4B 04 5B C2 14 00 3B C6 7E 03"), 3); // Y- axis
+ exe.setNop(exe.find("89 73 04 5F 5E 5B C2 14 00"), 3); // Y+ axis
+ }
+ if (iniUnlockCursor)
+ {
+ exe.setNop(0x00159A72, 6); // X- axis 1
+ exe.setNop(0x00159A8F, 6); // X+ axis 1
+ exe.setNop(0x00159AE5, 6); // Y+ axis 1
+ exe.setNop(0x00159B00, 10); // Y- axis 1 cave
+ exe.setNop(0x00159B19, 6); // Y- axis 1 island
+ exe.setNop(0x00159EAD, 6); // X- axis 2
+ exe.setNop(0x00159ECA, 6); // X+ axis 2
+ exe.setNop(0x00159EE7, 6); // Y+ axis 2
+ exe.setNop(0x00159F02, 10); // Y- axis 2 cave
+ exe.setNop(0x00159F1B, 6); // Y- axis 2 island
+ }
+}
+
+// ---- Main ----
+
+int getVersion(DWORD timeDateStamp)
+{
+ int id = wk::getGameID(timeDateStamp);
+ switch (id)
+ {
+ case wk::GAMEID_WA_3_6_31:
+ case wk::GAMEID_WA_3_7_2_1:
+ case wk::GAMEID_WA_3_8_CD:
+ return id;
+ default:
+ return 0;
+ }
+}
+
+BOOL WINAPI DllMain(HMODULE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ wk::Exe exe;
+ int version = getVersion(exe.FileHeader->TimeDateStamp);
+ if (version)
+ {
+ init(version);
+ patch(exe, version);
+ }
+ else
+ {
+ MessageBox(NULL, "wkUnlimiter is incompatible with your game version. Please run the 3.6.31.0, "
+ "3.7.2.1, or 3.8 CD release of Worms Armageddon. Otherwise, you can delete the module to remove "
+ "this warning.", "wkUnlimiter", MB_ICONWARNING);
+ }
+ }
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
diff --git a/src/tool/wkUnlimiter/wkConfig.cpp b/src/module/wkUnlimiter/wkConfig.cpp
similarity index 58%
rename from src/tool/wkUnlimiter/wkConfig.cpp
rename to src/module/wkUnlimiter/wkConfig.cpp
index b09888d..522ce1b 100644
--- a/src/tool/wkUnlimiter/wkConfig.cpp
+++ b/src/module/wkUnlimiter/wkConfig.cpp
@@ -3,36 +3,36 @@
namespace wk
{
- Config::Config(LPCSTR fileName)
+ Ini::Ini(LPCSTR fileName)
{
GetModuleFileName(NULL, _filePath, MAX_PATH);
char* sepIdx = strrchr(_filePath, '\\') + 1;
strcpy_s(sepIdx, MAX_PATH - (int)(sepIdx - _filePath), fileName);
}
- void Config::get(LPCSTR category, LPCSTR key, BOOL& result, UINT fallback) const
+ void Ini::get(LPCSTR category, LPCSTR key, BOOL& result, UINT fallback) const
{
result = GetPrivateProfileInt(category, key, fallback, _filePath);
}
- void Config::get(LPCSTR category, LPCSTR key, UINT& result, UINT fallback) const
+ void Ini::get(LPCSTR category, LPCSTR key, UINT& result, UINT fallback) const
{
result = GetPrivateProfileInt(category, key, fallback, _filePath);
}
- void Config::get(LPCSTR category, LPCSTR key, LPSTR result, INT resultLength, LPCSTR fallback) const
+ void Ini::get(LPCSTR category, LPCSTR key, LPSTR result, INT resultLength, LPCSTR fallback) const
{
GetPrivateProfileString(category, key, fallback, result, resultLength, _filePath);
}
- void Config::set(LPCSTR category, LPCSTR key, UINT value) const
+ void Ini::set(LPCSTR category, LPCSTR key, UINT value) const
{
CHAR buffer[32];
sprintf_s(buffer, "%d", value);
WritePrivateProfileString(category, key, buffer, _filePath);
}
- void Config::set(LPCSTR category, LPCSTR key, LPCSTR value) const
+ void Ini::set(LPCSTR category, LPCSTR key, LPCSTR value) const
{
WritePrivateProfileString(category, key, value, _filePath);
}
diff --git a/src/tool/wkUnlimiter/wkConfig.h b/src/module/wkUnlimiter/wkConfig.h
similarity index 88%
rename from src/tool/wkUnlimiter/wkConfig.h
rename to src/module/wkUnlimiter/wkConfig.h
index d754698..cf8f184 100644
--- a/src/tool/wkUnlimiter/wkConfig.h
+++ b/src/module/wkUnlimiter/wkConfig.h
@@ -3,10 +3,10 @@
namespace wk
{
- class Config
+ class Ini
{
public:
- Config(LPCSTR fileName);
+ Ini(LPCSTR fileName);
void get(LPCSTR category, LPCSTR key, BOOL& result, UINT fallback) const;
void get(LPCSTR category, LPCSTR key, UINT& result, UINT fallback) const;
diff --git a/src/tool/wkUnlimiter/wkUnlimiter.vcxproj b/src/module/wkUnlimiter/wkUnlimiter.vcxproj
similarity index 96%
rename from src/tool/wkUnlimiter/wkUnlimiter.vcxproj
rename to src/module/wkUnlimiter/wkUnlimiter.vcxproj
index 5e6f35e..db3e9b6 100644
--- a/src/tool/wkUnlimiter/wkUnlimiter.vcxproj
+++ b/src/module/wkUnlimiter/wkUnlimiter.vcxproj
@@ -93,7 +93,7 @@
-
+
{068a8647-0a66-4e39-983b-43aceac5c937}
diff --git a/src/tool/wkUnlimiter/wkUnlimiter.vcxproj.filters b/src/module/wkUnlimiter/wkUnlimiter.vcxproj.filters
similarity index 100%
rename from src/tool/wkUnlimiter/wkUnlimiter.vcxproj.filters
rename to src/module/wkUnlimiter/wkUnlimiter.vcxproj.filters
diff --git a/src/tool/WormKitTools/include/wkExe.h b/src/tool/WormKitTools/include/wkExe.h
deleted file mode 100644
index 8da2e3c..0000000
--- a/src/tool/WormKitTools/include/wkExe.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-#include
-
-namespace wk
-{
- struct Exe
- {
- public:
- HANDLE Handle;
- IMAGE_DOS_HEADER* DosHeader;
- IMAGE_NT_HEADERS* NtHeader;
- IMAGE_FILE_HEADER* FileHeader;
- IMAGE_OPTIONAL_HEADER* OptionalHeader;
-
- Exe(HMODULE hModule = NULL);
-
- ULONG_PTR Offset(ULONG_PTR off);
- BOOL IsCode(LPVOID ptr);
- BOOL IsData(LPVOID ptr);
- };
-}
diff --git a/src/tool/WormKitTools/include/wkPatch.h b/src/tool/WormKitTools/include/wkPatch.h
deleted file mode 100644
index 64ee0bb..0000000
--- a/src/tool/WormKitTools/include/wkPatch.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#pragma once
-#include
-
-namespace wk
-{
- enum InsertJump
- {
- IJ_JUMP, // Insert a jump (0xE9) with patchJump
- IJ_CALL, // Insert a call (0xE8) with patchJump
- IJ_FARJUMP, // Insert a farjump (0xEA) with patchJump
- IJ_FARCALL, // Insert a farcall (0x9A) with patchJump
- IJ_PUSHRET, // Insert a pushret with patchJump
- };
-
- struct Patch
- {
- public:
- ULONG_PTR position;
-
- Patch(ULONG_PTR address, SIZE_T size);
- ~Patch();
-
- void close() const;
- template void write(const T& value);
-
- static void byte(ULONG_PTR address, BYTE newValue);
- static void nops(ULONG_PTR address, SIZE_T size);
- static void jump(ULONG_PTR address, SIZE_T size, PVOID callee, DWORD jumpType);
-
- private:
- LPBYTE _address;
- SIZE_T _size;
- DWORD _oldProtect;
- };
-}
-
-#include "wkPatch.inl"
diff --git a/src/tool/WormKitTools/src/wkExe.cpp b/src/tool/WormKitTools/src/wkExe.cpp
deleted file mode 100644
index cadd545..0000000
--- a/src/tool/WormKitTools/src/wkExe.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#include "wkExe.h"
-
-namespace wk
-{
- Exe::Exe(HMODULE hModule)
- {
- Handle = hModule == 0 ? GetModuleHandleA(NULL) : hModule;
- DosHeader = (IMAGE_DOS_HEADER*)Handle;
- NtHeader = (IMAGE_NT_HEADERS*)((DWORD)DosHeader + DosHeader->e_lfanew);
- FileHeader = (IMAGE_FILE_HEADER*)&NtHeader->FileHeader;
- OptionalHeader = (IMAGE_OPTIONAL_HEADER*)&NtHeader->OptionalHeader;
- }
-
- ULONG_PTR Exe::Offset(ULONG_PTR off)
- {
- return (DWORD)Handle + off;
- }
-
- BOOL Exe::IsCode(LPVOID ptr)
- {
- return DWORD(ptr) >= Offset(OptionalHeader->BaseOfCode)
- && DWORD(ptr) < Offset(OptionalHeader->BaseOfCode) + OptionalHeader->SizeOfCode;
- }
-
- BOOL Exe::IsData(LPVOID ptr)
- {
- return DWORD(ptr) >= Offset(OptionalHeader->BaseOfData)
- && DWORD(ptr) < Offset(OptionalHeader->BaseOfData) + OptionalHeader->SizeOfInitializedData + OptionalHeader->SizeOfUninitializedData;
- }
-}
diff --git a/src/tool/WormKitTools/src/wkPatch.cpp b/src/tool/WormKitTools/src/wkPatch.cpp
deleted file mode 100644
index da67642..0000000
--- a/src/tool/WormKitTools/src/wkPatch.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-#include "wkPatch.h"
-#include
-
-namespace wk
-{
- Patch::Patch(ULONG_PTR address, SIZE_T size)
- : _address(reinterpret_cast(address))
- , _size(size)
- , position(0)
- {
- if (!_address || !_size)
- throw std::invalid_argument("Address and size must not be 0.");
- if (!VirtualProtect(_address, _size, PAGE_EXECUTE_READWRITE, &_oldProtect))
- throw std::exception("VirtualProtect failed, call GetLastError for more info.");
- }
-
- Patch::~Patch()
- {
- close();
- }
-
- void Patch::close() const
- {
- DWORD oldProtect;
- if (!VirtualProtect(_address, _size, _oldProtect, &oldProtect))
- throw std::exception("VirtualProtect failed, call GetLastError for more info.");
- }
-
- void Patch::byte(ULONG_PTR address, BYTE newValue)
- {
- wk::Patch patch(address, 1);
- patch.write(newValue);
- }
-
- void Patch::nops(ULONG_PTR address, SIZE_T size)
- {
- wk::Patch patch(address, size);
- while (size--)
- patch.write(0x90);
- }
-
- void Patch::jump(ULONG_PTR address, SIZE_T size, PVOID callee, DWORD jumpType)
- {
- wk::Patch patch(address, size);
-
- if (size >= 5 && address)
- {
- BYTE opSize, opCode;
- switch (jumpType)
- {
- case IJ_PUSHRET: opSize = 6; opCode = 0x68; break;
- case IJ_FARJUMP: opSize = 7; opCode = 0xEA; break;
- case IJ_FARCALL: opSize = 7; opCode = 0x9A; break;
- case IJ_CALL: opSize = 5; opCode = 0xE8; break;
- default: opSize = 5; opCode = 0xE9; break;
- }
-
- if (size < opSize)
- throw std::exception("Not enough space to patch opcode.");
-
- patch.write(opCode);
- switch (opSize)
- {
- case 7:
- patch.write((ULONG)callee);
- patch.write(0x23);
- break;
- case 6:
- patch.write((ULONG)callee);
- patch.write(0xC3);
- break;
- default:
- patch.write((ULONG)callee - address - 5);
- break;
- }
- for (DWORD i = opSize; i < size; i++)
- patch.write(0x90);
- }
- }
-};
diff --git a/src/tool/wkUnlimiter/main.cpp b/src/tool/wkUnlimiter/main.cpp
deleted file mode 100644
index f826c5c..0000000
--- a/src/tool/wkUnlimiter/main.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-#define WIN32_LEAN_AND_MEAN
-#include
-#include "wkConfig.h"
-#include "wkExe.h"
-#include "wkPatch.h"
-#include "wkUtils.h"
-
-// ---- Configuration ----
-
-BOOL cfgAllowMultiInstance;
-BOOL cfgEnableAllControls;
-BOOL cfgUnlockCamera;
-BOOL cfgUnlockCursor;
-
-void configure()
-{
- wk::Config config("wkUnlimiter.ini");
-
- // Load INI settings.
- config.get("Common", "AllowMultiInstance", cfgAllowMultiInstance, TRUE);
- config.get("Frontend", "EnableAllControls", cfgEnableAllControls, TRUE);
- config.get("Game", "UnlockCamera", cfgUnlockCamera, TRUE);
- config.get("Game", "UnlockCursor", cfgUnlockCursor, TRUE);
-
- // Ensure INI file has been created with default setting.
- config.set("Common", "AllowMultiInstance", cfgAllowMultiInstance);
- config.set("Frontend", "EnableAllControls", cfgEnableAllControls);
- config.set("Game", "UnlockCamera", cfgUnlockCamera);
- config.set("Game", "UnlockCursor", cfgUnlockCursor);
-}
-
-// ---- Patch ----
-
-void patch(wk::Exe& exe, int gameVersion)
-{
- if (cfgAllowMultiInstance)
- {
- wk::Patch patch(exe.Offset(0x000E7AD1), 1);
- patch.write((char)0xEB); // Requires WormKitDS as game executable loads modules after this patched out check.
- }
- if (cfgEnableAllControls)
- {
- wk::Patch patch(exe.Offset(0x001C5D26), 4);
- patch.write(0x9090016A); // CWnd::EnableWindow(bEnable) -> CWnd::EnableWindow(TRUE)
- }
- if (cfgUnlockCamera)
- {
- wk::Patch::nops(exe.Offset(0x00142A89), 2); // X- axis
- wk::Patch::nops(exe.Offset(0x00142A91), 2); // X+ axis
- wk::Patch::nops(exe.Offset(0x00142AA7), 3); // Y- axis
- wk::Patch::nops(exe.Offset(0x00142A9C), 3); // Y+ axis
- }
- if (cfgUnlockCursor)
- {
- wk::Patch::nops(exe.Offset(0x00159EAD), 6); // X- axis 1
- wk::Patch::nops(exe.Offset(0x00159A72), 6); // X- axis 2
- wk::Patch::nops(exe.Offset(0x00159ECA), 6); // X+ axis 1
- wk::Patch::nops(exe.Offset(0x00159A8F), 6); // X+ axis 2
- wk::Patch::nops(exe.Offset(0x00159B00), 10); // Y- axis 1 cave
- wk::Patch::nops(exe.Offset(0x00159F02), 10); // Y- axis 2 cave
- wk::Patch::nops(exe.Offset(0x00159B19), 6); // Y- axis 1 island
- wk::Patch::nops(exe.Offset(0x00159F1B), 6); // Y- axis 2 island
- wk::Patch::nops(exe.Offset(0x00159AE5), 6); // Y+ axis 1
- wk::Patch::nops(exe.Offset(0x00159EE7), 6); // Y+ axis 2
- }
-}
-
-// ---- Main ----
-
-int getVersion(DWORD timeDateStamp)
-{
- int id = wk::getGameID(timeDateStamp);
- switch (id)
- {
- case wk::GAMEID_WA_3_8_CD:
- return id;
- default:
- return 0;
- }
-}
-
-BOOL WINAPI DllMain(HMODULE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
-{
- switch (fdwReason)
- {
- case DLL_PROCESS_ATTACH:
- {
- wk::Exe exe;
- int version = getVersion(exe.FileHeader->TimeDateStamp);
- if (version)
- {
- configure();
- patch(exe, version);
- }
- else
- {
- MessageBox(NULL, "wkUnlimiter is incompatible with your game version. Please run the 3.8 CD release of "
- "Worms Armageddon. Otherwise, you can delete the module to remove this warning.", "wkUnlimiter",
- MB_ICONWARNING);
- }
- }
- break;
-
- case DLL_PROCESS_DETACH:
- break;
- }
- return TRUE;
-}