Compare commits

...

18 Commits

Author SHA1 Message Date
Ray
914acc2e1b Zero-terminate Data to prevent client-side bugs.
- Fixes chat messages displaying stale memory as the client discards the data length.
2024-05-16 21:30:35 +02:00
Ray
b4e6433545 Fix deprecation and nullability warnings. 2024-05-16 12:02:48 +02:00
Ray
63691f897b Update app target framework to .NET 8. 2024-05-16 12:02:01 +02:00
Ray
b509d7bdaf Update test dependencies. 2024-05-16 12:01:56 +02:00
Ray
046033bba7 Update platform toolset. 2024-05-16 12:01:14 +02:00
Ray
6dc2de2445 Update dependencies (same major version only). 2024-05-16 12:00:51 +02:00
Ray
48f1f91be3 Update copyright. 2024-05-16 11:58:06 +02:00
Ray
cbe1388fb0 Fix typo. 2021-09-12 16:56:41 +02:00
Ray
b68503e609 Release 4.0.4 2021-09-12 16:54:04 +02:00
Ray
5fdd97c5ad Add missing StrikeClusterDamage field. 2021-09-12 16:53:19 +02:00
Ray
6a418e84ae Update release notes. 2021-09-12 13:18:07 +02:00
Ray
8eb0a971e8 Release 4.0.3: Fix StackOverflowException when using legacy .NET versions.
Sadly requires all packages to update due to fixed version ProjectReferences.
2021-09-12 13:14:23 +02:00
Ray
6cba058138 Fix StreamShims Read method to not call itself. 2021-09-12 12:30:17 +02:00
Ray
03095916f1 MSBuild: Change common target paths in project files to fix building for DocFX. 2021-03-24 19:27:22 +01:00
Ray Koopa
9a218549e7 Mention new module folder. 2020-07-21 21:08:41 +02:00
Ray Koopa
a99a883f6f Move WormKit loaders, modules, and libraries to module sub folder. Add signature scanning and import replacing. 2020-07-21 21:06:03 +02:00
Ray Koopa
518207b7e6 Add AllowMultiInstance. 2020-07-20 20:17:20 +02:00
Ray Koopa
2b94e09e39 Move FrontendKitLib to WormKitTools to reuse it for other modules. 2020-07-20 18:38:10 +02:00
62 changed files with 1106 additions and 367 deletions

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2017-2020 Syroot
Copyright (c) 2017-2024 Syroot
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -28,17 +28,17 @@ This repository hosts .NET libraries which can import, modify, and export the fo
Implementation of formats listed above as unsupported is planned for a later date.
The libraries are available on [NuGet](https://www.nuget.org/packages?q=Syroot.Worms).
## Modules
* `fkNetcode`: Patches Worms 2's outdated external IP detection and resolves it properly via a web service.
* `fkDesPatch`: Unfinished module meant to replace functionality found in Sn*tch patcher.
* `FrontendKitWS`: WormKit-like module loader for patching the Worms 2 Frontend.
* `WormKitLib`: Utilities like signature scanning or import replacement to help in patching Worms executables.
## Tools
* `Syroot.Worms.Mgame.Launcher`: Creates a fake launch configuration to start OW or WWPA clients with.
* `Syroot.Worms.Mgame.GameServer`: Simulates OW or WWPA networking to allow playing games.
* `Syroot.Worms.Worms2.GameServer`: Simulates a Worms 2 server.
## Modules
* `FrontendKitWS`: WormKit-like module loader for patching the Worms 2 Frontend.
* `fkNetcode`: Patches Worms 2's outdated external IP detection and resolves it properly via a web service.
## Availability
The libraries are available on [NuGet](https://www.nuget.org/packages?q=Syroot.Worms).

View File

@ -49,11 +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}") = "FrontendKitLib", "tool\FrontendKitLib\FrontendKitLib.vcxproj", "{068A8647-0A66-4E39-983B-43ACEAC5C937}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FrontendKitWS", "module\FrontendKitWS\FrontendKitWS.vcxproj", "{E391EA12-B929-466C-932F-DEF72B8CEB5D}"
EndProject
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
@ -129,18 +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
{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
@ -163,9 +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}
{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}

View File

@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)build.xml" />
<Import Project="$(MSBuildThisFileDirectory)..\..\build.xml" />
<!-- Metadata -->
<PropertyGroup>
<AssemblyName>Syroot.Worms.Armageddon.ProjectX</AssemblyName>
<Description>.NET library for loading and modifying files of Worms Armageddon ProjectX.</Description>
<PackageReleaseNotes>Overhaul implementation and documentation.</PackageReleaseNotes>
<PackageReleaseNotes>Fix StackOverflowException when using legacy .NET versions.</PackageReleaseNotes>
<PackageTags>$(PackageTags);project x;worms armageddon</PackageTags>
<Version>4.0.0</Version>
<Version>4.0.3</Version>
</PropertyGroup>
<!-- References -->

View File

@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)build.xml" />
<Import Project="$(MSBuildThisFileDirectory)..\..\build.xml" />
<!-- Metadata -->
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Description>.NET library for loading and modifying files of Team17's Worms Armageddon.</Description>
<PackageReleaseNotes>Overhaul implementation and documentation. Implement W:A V3 scheme format.</PackageReleaseNotes>
<PackageReleaseNotes>Fix StackOverflowException when using legacy .NET versions.</PackageReleaseNotes>
<PackageTags>$(PackageTags);worms armageddon</PackageTags>
<Version>4.0.2</Version>
<Version>4.0.3</Version>
</PropertyGroup>
<!-- References -->

View File

@ -1,17 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)build.xml" />
<Import Project="$(MSBuildThisFileDirectory)..\..\build.xml" />
<!-- Metadata -->
<PropertyGroup>
<Description>.NET library for loading and modifying files of Mgame Worms clients.</Description>
<PackageReleaseNotes>Overhaul implementation and documentation.</PackageReleaseNotes>
<PackageReleaseNotes>Fix StackOverflowException when using legacy .NET versions.</PackageReleaseNotes>
<PackageTags>$(PackageTags);online worms;worms world party aqua</PackageTags>
<Version>4.0.0</Version>
<Version>4.0.3</Version>
</PropertyGroup>
<!-- References -->
<ItemGroup>
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.7.1" />
<ProjectReference Include="..\Syroot.Worms\Syroot.Worms.csproj" />
</ItemGroup>

View File

@ -1,13 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)build.xml" />
<Import Project="$(MSBuildThisFileDirectory)..\..\build.xml" />
<!-- Metadata -->
<PropertyGroup>
<AssemblyName>Syroot.Worms.WorldParty</AssemblyName>
<Description>.NET library for loading and modifying files of Team17's Worms World Party.</Description>
<PackageReleaseNotes>Overhaul implementation and documentation.</PackageReleaseNotes>
<PackageReleaseNotes>Fix StackOverflowException when using legacy .NET versions.</PackageReleaseNotes>
<PackageTags>$(PackageTags);worms world party</PackageTags>
<Version>4.0.0</Version>
<Version>4.0.3</Version>
</PropertyGroup>
<!-- References -->

View File

@ -76,6 +76,8 @@ namespace Syroot.Worms.Worms2
public int DiggingTime;
/// <summary>Amount of airstrike clusters thrown.</summary>
public int StrikeClusterCount;
/// <summary>Damage of airstrike clusters measured in health points which also determines the blast radius.</summary>
public int StrikeClusterDamage;
/// <summary>Angle in which bullets are dispersed, measured in degrees.</summary>
public int BulletSpreadAngle;

View File

@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)build.xml" />
<Import Project="$(MSBuildThisFileDirectory)..\..\build.xml" />
<!-- Metadata -->
<PropertyGroup>
<Description>.NET library for loading and modifying files of Team17's Worms 2.</Description>
<PackageReleaseNotes>Overhaul implementation and documentation.</PackageReleaseNotes>
<PackageReleaseNotes>Add missing SchemeWeapon StrikeClusterDamage field.</PackageReleaseNotes>
<PackageTags>$(PackageTags);worms 2</PackageTags>
<Version>4.0.0</Version>
<Version>4.0.4</Version>
</PropertyGroup>
<!-- References -->

View File

@ -22,7 +22,7 @@ namespace System.IO
public static int Read(this Stream stream, Span<byte> buffer)
{
byte[] bytes = new byte[buffer.Length];
int bytesRead = stream.Read(bytes);
int bytesRead = stream.Read(bytes, 0, bytes.Length);
bytes.AsSpan(0, bytesRead).CopyTo(buffer);
return bytesRead;
}

View File

@ -1,22 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)build.xml" />
<Import Project="$(MSBuildThisFileDirectory)..\..\build.xml" />
<!-- Metadata -->
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Description>.NET library for loading and modifying files of Team17 Worms games.</Description>
<PackageReleaseNotes>Overhaul implementation and documentation.</PackageReleaseNotes>
<Version>4.0.0</Version>
<PackageReleaseNotes>Fix StackOverflowException when using legacy .NET versions.</PackageReleaseNotes>
<Version>4.0.3</Version>
</PropertyGroup>
<!-- References -->
<ItemGroup>
<PackageReference Include="Syroot.BinaryData" Version="5.2.1" />
<PackageReference Include="System.Drawing.Common" Version="4.5.0" />
<PackageReference Include="Syroot.BinaryData" Version="5.2.2" />
<PackageReference Include="System.Drawing.Common" Version="4.7.3" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.0.0" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.0" />
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
</ItemGroup>
</Project>
</Project>

View File

@ -35,13 +35,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>

View File

@ -14,20 +14,21 @@
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{068a8647-0a66-4e39-983b-43aceac5c937}</ProjectGuid>
<RootNamespace>FrontendKitLib</RootNamespace>
<RootNamespace>WormKitTools</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>WormKitTools</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
@ -92,24 +93,25 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\fkConfig.cpp" />
<ClCompile Include="src\fkPatch.cpp" />
<ClCompile Include="src\fkUtils.cpp" />
<ClCompile Include="src\wkIni.cpp" />
<ClCompile Include="src\wkPatch.cpp" />
<ClCompile Include="src\wkUtils.cpp" />
<ClCompile Include="src\pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="src\PEInfo.cpp" />
<ClCompile Include="src\wkExe.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\fkConfig.h" />
<ClInclude Include="include\fkPatch.h" />
<ClInclude Include="include\fkUtils.h" />
<ClInclude Include="include\PEInfo.h" />
<ClInclude Include="include\wkIni.h" />
<ClInclude Include="include\wkPatch.h" />
<ClInclude Include="include\wkUtils.h" />
<ClInclude Include="include\wkExe.h" />
<ClInclude Include="src\pch.h" />
</ItemGroup>
<ItemGroup>
<None Include="include\fkPatch.inl" />
<None Include="include\wkExe.inl" />
<None Include="include\wkPatch.inl" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -15,41 +15,44 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\PEInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\fkUtils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\fkPatch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\fkConfig.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\wkUtils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\wkPatch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\wkExe.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\wkIni.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\fkConfig.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\fkPatch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\fkUtils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\PEInfo.h">
<ClInclude Include="include\wkUtils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\wkPatch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\wkExe.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\wkIni.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="include\fkPatch.inl">
<None Include="include\wkPatch.inl">
<Filter>Header Files</Filter>
</None>
<None Include="include\wkExe.inl">
<Filter>Header Files</Filter>
</None>
</ItemGroup>

View File

@ -0,0 +1,88 @@
#pragma once
#include <stdint.h>
#include <string>
#include <Windows.h>
#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 ------------------------------------------------------------------------------------------------
/// <summary>
/// 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.
/// </summary>
/// <param name="signature">The signature to find.</param>
/// <returns>The offset of the first match of the signature.</returns>
ULONG_PTR find(std::string signature);
/// <summary>
/// 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.
/// </summary>
/// <param name="signature">The signature to find.</param>
/// <returns>The offset of the first match of the signature.</returns>
ULONG_PTR find(int16_t signature[], size_t signatureSize); // any non-uint8_t value is a wildcard
/// <summary>
/// Writes the given value to the specified offset.
/// </summary>
/// <typeparam name="T">The type of the value to write.</typeparam>
/// <param name="offset">The relative address at which to write the value.</param>
/// <param name="value">The value to write.</param>
template <class T> void set(ULONG_PTR offset, T value);
/// <summary>
/// Replaces the given import with the specified hook, which must have the same signature.
/// </summary>
/// <param name="import">The imported method to replace.</param>
/// <param name="hook">The method to replace the import with.</param>
void setImp(LPVOID import, LPVOID hook);
/// <summary>
/// Writes a jump to the given callee at the specified offset.
/// </summary>
/// <param name="offset">The relative address at which to write the value.</param>
/// <param name="size">The number of bytes overwritten for the jump opcode.</param>
/// <param name="callee">The called method.</param>
/// <param name="jumpType">The type of the jump to insert.</param>
void setJmp(ULONG_PTR offset, SIZE_T size, LPVOID callee, DWORD jumpType);
/// <summary>
/// Nops out the given number of bytes at the specified offset.
/// </summary>
/// <param name="offset">The relative address at which to nop out code.</param>
/// <param name="size">The number of bytes to nop out.</param>
void setNop(ULONG_PTR offset, SIZE_T size);
private:
LPVOID getAddress(ULONG_PTR offset);
PIMAGE_IMPORT_DESCRIPTOR getImports();
};
}
#include "wkExe.inl"

View File

@ -0,0 +1,9 @@
namespace wk
{
template <class T>
void Exe::set(ULONG_PTR offset, T newValue)
{
Patch patch(getAddress(offset), sizeof(T));
patch.write(newValue);
}
}

View File

@ -1,12 +1,12 @@
#pragma once
#include <Windows.h>
namespace fk
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;

View File

@ -0,0 +1,31 @@
#pragma once
#include <Windows.h>
namespace wk
{
struct Patch
{
public:
// ---- FIELDS -------------------------------------------------------------------------------------------------
ULONG_PTR position;
// ---- CONSTRUCTORS & DESTRUCTOR ------------------------------------------------------------------------------
Patch(LPVOID address, SIZE_T size);
~Patch();
// ---- METHODS ------------------------------------------------------------------------------------------------
void close() const;
template <class T> void write(const T& value);
private:
// ---- FIELDS -------------------------------------------------------------------------------------------------
LPBYTE _address;
SIZE_T _size;
DWORD _oldProtect;
};
}
#include "wkPatch.inl"

View File

@ -1,4 +1,4 @@
namespace fk
namespace wk
{
template <class T>
void Patch::write(const T& value)

View File

@ -0,0 +1,43 @@
#pragma once
#include <stdexcept>
#include <Windows.h>
namespace wk
{
// 0x 00 0000 00
// [Game][Version][Release]
enum GameID
{
GAMEID_NONE,
GAMEID_W2 = 0x20000000,
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 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);
std::string getErrorMessage(int error);
}

View File

@ -0,0 +1,160 @@
#include "wkExe.h"
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <vector>
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<std::string> begin(iss), end;
std::vector<std::string> tokens(begin, end);
std::vector<int16_t> 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<WORD>(0x23);
break;
case 6:
patch.write((ULONG)callee);
patch.write<BYTE>(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;
}
}

View File

@ -1,38 +1,38 @@
#include "fkConfig.h"
#include "wkIni.h"
#include <stdio.h>
namespace fk
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);
}

View File

@ -0,0 +1,32 @@
#include "wkPatch.h"
#include <stdexcept>
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.");
}
};

View File

@ -1,21 +1,24 @@
#include "fkUtils.h"
#include "wkUtils.h"
#include <string>
#include "fkPatch.h"
#include "wkPatch.h"
namespace fk
namespace wk
{
int getGameVersion(DWORD timeDateStamp)
int getGameID(DWORD timeDateStamp)
{
switch (timeDateStamp)
{
case 0x3528DAFA: return GAME_VERSION_BR;
case 0x3528DCB1: return GAME_VERSION_EN;
case 0x3528DB52: return GAME_VERSION_GE;
case 0x3528DA98: return GAME_VERSION_NA;
case 0x3528DBDA: return GAME_VERSION_SA;
case 0x3587BE19: return GAME_VERSION_TRY;
case 0x3528DAFA: return GAMEID_W2_1_05_BR;
case 0x3528DCB1: return GAMEID_W2_1_05_EN;
case 0x3528DB52: return GAMEID_W2_1_05_GE;
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;
}
return GAME_VERSION_NONE;
}
std::string getErrorMessage(int error)

View File

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{6b4d57ea-4642-440a-ab62-2e011d7b64e1}</ProjectGuid>
<RootNamespace>fkDesPatch</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>bin\$(Configuration)\</OutDir>
<IntDir>obj\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>bin\$(Configuration)\</OutDir>
<IntDir>obj\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;FKDESPATCH_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)..\WormKitTools\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;FKDESPATCH_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)..\WormKitTools\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WormKitTools\WormKitTools.vcxproj">
<Project>{068a8647-0a66-4e39-983b-43aceac5c937}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,84 @@
#define WIN32_LEAN_AND_MEAN
#include <stdint.h>
#include <Windows.h>
#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;
}

View File

@ -22,13 +22,13 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
@ -60,7 +60,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;FKNETCODE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)..\FrontendKitLib\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)..\WormKitTools\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -77,7 +77,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;FKNETCODE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)..\FrontendKitLib\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)..\WormKitTools\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -98,7 +98,7 @@
<ResourceCompile Include="fkNetcode.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FrontendKitLib\FrontendKitLib.vcxproj">
<ProjectReference Include="..\WormKitTools\WormKitTools.vcxproj">
<Project>{068a8647-0a66-4e39-983b-43aceac5c937}</Project>
</ProjectReference>
</ItemGroup>

View File

@ -2,36 +2,36 @@
#include <Windows.h>
#include <WinInet.h>
#include <winsock.h>
#include "fkConfig.h"
#include "fkPatch.h"
#include "fkUtils.h"
#include "PEInfo.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()
{
fk::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,10 +84,10 @@ 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", fk::getErrorMessage(error).c_str());
sprintf_s(msg, "Could not resolve your IP through the web service. %s", wk::getErrorMessage(error).c_str());
MessageBox(NULL, msg, "fkNetcode", MB_ICONWARNING);
}
return !error;
@ -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;
}
@ -134,45 +134,62 @@ bool __stdcall patchResolveIP(LPSTR buffer, int bufferLength)
// ---- Patch ----
void patch(PEInfo& pe, int gameVersion)
void patch(wk::Exe& exe, int gameVersion)
{
fk::Patch::jump(pe.Offset(0x00001799), 5, &patchResolveIP, fk::IJ_JUMP); // replace IP resolve with web service
exe.setJmp(0x00001799, 5, &patchResolveIP, wk::JT_JMP); // replace IP resolve with web service
if (gameVersion == fk::GAME_VERSION_TRY)
if (gameVersion == wk::GAMEID_W2_1_07_TRY)
{
fk::Patch::nops(pe.Offset(0x00053B96), 5); // prevent overriding IP with user name
fk::Patch::nops(pe.Offset(0x00054693), 5); // prevent overriding IP with NAT IP
fk::Patch::nops(pe.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
{
fk::Patch::nops(pe.Offset(0x00053E96), 5); // prevent overriding IP with user name
fk::Patch::nops(pe.Offset(0x00054935), 11); // useless sleep when connecting to server
fk::Patch::nops(pe.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
}
}
// ---- 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:
{
PEInfo pe;
int version = fk::getGameVersion(pe.FH->TimeDateStamp);
if (version == fk::GAME_VERSION_NONE)
wk::Exe exe;
int version = getVersion(exe.FileHeader->TimeDateStamp);
if (version)
{
init();
patch(exe, version);
}
else
{
MessageBox(NULL, "fkNetcode 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.", "fkNetcode",
MB_ICONWARNING);
}
else
{
configure();
patch(pe, version);
}
}
break;

View File

@ -0,0 +1,132 @@
#define WIN32_LEAN_AND_MEAN
#include <stdint.h>
#include <Windows.h>
#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;
}

View File

@ -0,0 +1,39 @@
#include "wkConfig.h"
#include <stdio.h>
namespace wk
{
Ini::Ini(LPCSTR fileName)
{
GetModuleFileName(NULL, _filePath, MAX_PATH);
char* sepIdx = strrchr(_filePath, '\\') + 1;
strcpy_s(sepIdx, MAX_PATH - (int)(sepIdx - _filePath), fileName);
}
void Ini::get(LPCSTR category, LPCSTR key, BOOL& result, UINT fallback) const
{
result = GetPrivateProfileInt(category, key, fallback, _filePath);
}
void Ini::get(LPCSTR category, LPCSTR key, UINT& result, UINT fallback) const
{
result = GetPrivateProfileInt(category, key, fallback, _filePath);
}
void Ini::get(LPCSTR category, LPCSTR key, LPSTR result, INT resultLength, LPCSTR fallback) const
{
GetPrivateProfileString(category, key, fallback, result, resultLength, _filePath);
}
void Ini::set(LPCSTR category, LPCSTR key, UINT value) const
{
CHAR buffer[32];
sprintf_s(buffer, "%d", value);
WritePrivateProfileString(category, key, buffer, _filePath);
}
void Ini::set(LPCSTR category, LPCSTR key, LPCSTR value) const
{
WritePrivateProfileString(category, key, value, _filePath);
}
}

View File

@ -0,0 +1,20 @@
#pragma once
#include <Windows.h>
namespace wk
{
class Ini
{
public:
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;
void get(LPCSTR category, LPCSTR key, LPSTR result, INT resultLength, LPCSTR fallback = NULL) const;
void set(LPCSTR category, LPCSTR key, UINT value) const;
void set(LPCSTR category, LPCSTR key, LPCSTR value) const;
private:
CHAR _filePath[MAX_PATH];
};
}

View File

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{cded4b7c-91df-45d3-9704-db8750bdaf5b}</ProjectGuid>
<RootNamespace>wkUnlimiter</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>bin\$(Configuration)\</OutDir>
<IntDir>obj\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>bin\$(Configuration)\</OutDir>
<IntDir>obj\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;WKUNLIMITER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)..\WormKitTools\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;WKUNLIMITER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)..\WormKitTools\include\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="wkConfig.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="wkConfig.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WormKitTools\WormKitTools.vcxproj">
<Project>{068a8647-0a66-4e39-983b-43aceac5c937}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="wkConfig.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="wkConfig.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -10,9 +10,9 @@
<!-- References -->
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="MSTest.TestAdapter" Version="2.1.2" />
<PackageReference Include="MSTest.TestFramework" Version="2.1.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
</ItemGroup>
<!-- Files Linking -->

View File

@ -1,5 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)test.xml" />
<Import Project="$(MSBuildThisFileDirectory)..\..\test.xml" />
<!-- References -->
<ItemGroup>

View File

@ -1,5 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)test.xml" />
<Import Project="$(MSBuildThisFileDirectory)..\..\test.xml" />
<!-- References -->
<ItemGroup>

View File

@ -1,5 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)test.xml" />
<Import Project="$(MSBuildThisFileDirectory)..\..\test.xml" />
<!-- References -->
<ItemGroup>

View File

@ -1,5 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)test.xml" />
<Import Project="$(MSBuildThisFileDirectory)..\..\test.xml" />
<!-- References -->
<ItemGroup>

View File

@ -1,5 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)test.xml" />
<Import Project="$(MSBuildThisFileDirectory)..\..\test.xml" />
<!-- References -->
<ItemGroup>

View File

@ -1,5 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(SolutionDir)test.xml" />
<Import Project="$(MSBuildThisFileDirectory)..\..\test.xml" />
<!-- References -->
<ItemGroup>

View File

@ -1,18 +0,0 @@
#pragma once
#include <Windows.h>
struct PEInfo
{
PEInfo(HMODULE hModule = 0);
void Reset(HMODULE hModule);
ULONG_PTR Offset(ULONG_PTR off);
BOOL IsCode(LPVOID ptr);
BOOL IsData(LPVOID ptr);
HANDLE Handle;
IMAGE_DOS_HEADER* DOS;
IMAGE_NT_HEADERS* NT;
IMAGE_FILE_HEADER* FH;
IMAGE_OPTIONAL_HEADER* OPT;
};

View File

@ -1,36 +0,0 @@
#pragma once
#include <Windows.h>
namespace fk
{
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 <class T> void write(const T& value);
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 "fkPatch.inl"

View File

@ -1,20 +0,0 @@
#pragma once
#include <stdexcept>
#include <Windows.h>
namespace fk
{
enum GameVersion
{
GAME_VERSION_NONE = -1,
GAME_VERSION_BR, // 1.05 Br
GAME_VERSION_EN, // 1.05 Du, En, Fr, It, Po, Sp, Sw
GAME_VERSION_GE, // 1.05
GAME_VERSION_NA, // 1.05
GAME_VERSION_SA, // 1.05
GAME_VERSION_TRY // 1.07 Trymedia
};
int getGameVersion(DWORD timeDateStamp);
std::string getErrorMessage(int error);
}

View File

@ -1,32 +0,0 @@
#include "PEInfo.h"
PEInfo::PEInfo(HMODULE hModule)
{
Reset(hModule);
}
void PEInfo::Reset(HMODULE hModule)
{
Handle = hModule == 0 ? GetModuleHandleA(NULL) : hModule;
DOS = (IMAGE_DOS_HEADER*)Handle;
NT = (IMAGE_NT_HEADERS*)((DWORD)DOS + DOS->e_lfanew);
FH = (IMAGE_FILE_HEADER*)&NT->FileHeader;
OPT = (IMAGE_OPTIONAL_HEADER*)&NT->OptionalHeader;
}
ULONG_PTR PEInfo::Offset(ULONG_PTR off)
{
return (DWORD)Handle + off;
}
BOOL PEInfo::IsCode(LPVOID ptr)
{
return DWORD(ptr) >= Offset(OPT->BaseOfCode)
&& DWORD(ptr) < Offset(OPT->BaseOfCode) + OPT->SizeOfCode;
}
BOOL PEInfo::IsData(LPVOID ptr)
{
return DWORD(ptr) >= Offset(OPT->BaseOfData)
&& DWORD(ptr) < Offset(OPT->BaseOfData) + OPT->SizeOfInitializedData + OPT->SizeOfUninitializedData;
}

View File

@ -1,74 +0,0 @@
#include "fkPatch.h"
#include <stdexcept>
namespace fk
{
Patch::Patch(ULONG_PTR address, SIZE_T size)
: _address(reinterpret_cast<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();
}
void Patch::close() const
{
DWORD oldProtect;
if (!VirtualProtect(_address, _size, _oldProtect, &oldProtect))
throw std::exception("VirtualProtect failed, call GetLastError for more info.");
}
void Patch::nops(ULONG_PTR address, SIZE_T size)
{
fk::Patch patch(address, size);
while (size--)
patch.write<BYTE>(0x90);
}
void Patch::jump(ULONG_PTR address, SIZE_T size, PVOID callee, DWORD jumpType)
{
fk::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<WORD>(0x23);
break;
case 6:
patch.write((ULONG)callee);
patch.write<BYTE>(0xC3);
break;
default:
patch.write((ULONG)callee - address - 5);
break;
}
for (DWORD i = opSize; i < size; i++)
patch.write<BYTE>(0x90);
}
}
};

View File

@ -1,4 +1,5 @@
using System.Net;
using System.Net.Http;
namespace Syroot.Worms.Mgame.GameServer
{
@ -33,8 +34,9 @@ namespace Syroot.Worms.Mgame.GameServer
// Retrieve external IP if not yet done and given IP is invalid.
if (_ipAddress == null && (IP == null || !IPAddress.TryParse(IP, out _ipAddress)))
{
using WebClient webClient = new WebClient();
_ipAddress = IPAddress.Parse(webClient.DownloadString("https://ip.syroot.com"));
using HttpClient httpClient = new HttpClient();
_ipAddress = IPAddress.Parse(
httpClient.GetStringAsync("https://ip.syroot.com").GetAwaiter().GetResult());
}
return _ipAddress;
}

View File

@ -4,12 +4,12 @@
<AssemblyName>Server</AssemblyName>
<LangVersion>latest</LangVersion>
<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp3</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.32" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.32" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.32" />
<PackageReference Include="Syroot.BinaryData.Memory" Version="5.2.2" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.7.1" />
<ProjectReference Include="..\..\library\Syroot.Worms.Mgame\Syroot.Worms.Mgame.csproj" />

View File

@ -16,9 +16,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Costura.Fody" Version="4.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.32" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.32" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.32" />
<ProjectReference Include="..\..\library\Syroot.Worms.Mgame\Syroot.Worms.Mgame.csproj" />
<ProjectReference Include="..\..\library\Syroot.Worms\Syroot.Worms.csproj" />
<Reference Include="System.Windows.Forms" />

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\library\Syroot.Worms.Armageddon.ProjectX\Syroot.Worms.Armageddon.ProjectX.csproj" />

View File

@ -40,7 +40,8 @@ namespace Syroot.Worms.Worms2.GameServer
Stream stream = client.GetStream();
_reader = PipeReader.Create(stream);
_writer = PipeWriter.Create(stream);
RemoteEndPoint = (IPEndPoint)client.Client.RemoteEndPoint;
RemoteEndPoint = client.Client.RemoteEndPoint as IPEndPoint
?? throw new ArgumentException("TCP client is not connected.", nameof(client));
}
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
@ -221,7 +222,7 @@ namespace Syroot.Worms.Worms2.GameServer
+ add(PacketField.Value4, packet.Value4, sizeof(int))
+ add(PacketField.Value10, packet.Value10, sizeof(int))
+ add(PacketField.DataLength, packet.Data, sizeof(int))
+ add(PacketField.Data, packet.Data, packet.Data?.Length ?? 0)
+ add(PacketField.Data, packet.Data, (packet.Data?.Length ?? 0) + 1)
+ add(PacketField.Error, packet.Error, sizeof(int))
+ add(PacketField.Name, packet.Name, 20)
+ add(PacketField.Session, packet.Session, Unsafe.SizeOf<SessionInfo>());
@ -243,8 +244,10 @@ namespace Syroot.Worms.Worms2.GameServer
if (packet.Value10 != null) writeInt(ref span, packet.Value10.Value);
if (packet.Data != null)
{
writeInt(ref span, packet.Data.Length);
writeInt(ref span, packet.Data.Length + 1);
span = span.Slice(Encodings.Windows1252.GetBytes(packet.Data, span));
span[0] = 0;
span = span.Slice(1);
}
if (packet.Error != null) writeInt(ref span, packet.Error.Value);
if (packet.Name != null)

View File

@ -23,9 +23,11 @@ namespace Syroot.Worms.Worms2.GameServer
private static IPEndPoint ParseEndPoint(string? s, IPEndPoint fallback)
{
if (UInt16.TryParse(s, out ushort port))
if (s == null)
return fallback;
else if (UInt16.TryParse(s, out ushort port))
return new IPEndPoint(fallback.Address, port);
else if (IPEndPoint.TryParse(s, out IPEndPoint endPoint))
else if (IPEndPoint.TryParse(s, out IPEndPoint? endPoint))
return endPoint;
else
return fallback;

View File

@ -405,7 +405,7 @@ namespace Syroot.Worms.Worms2.GameServer
return;
// Require valid room ID and IP.
if (IPAddress.TryParse(packet.Data, out IPAddress ip) && connection.RemoteEndPoint.Address.Equals(ip))
if (IPAddress.TryParse(packet.Data, out IPAddress? ip) && connection.RemoteEndPoint.Address.Equals(ip))
{
Game newGame = new Game(++_lastID, fromUser.Name, fromUser.Session.Nation, fromUser.RoomID,
connection.RemoteEndPoint.Address, // do not use bad NAT IP reported by users here

View File

@ -8,13 +8,13 @@
<Authors>Syroot</Authors>
<Copyright>(c) Syroot, licensed under MIT</Copyright>
<Description>Worms 2 Game Server</Description>
<Version>1.1.0</Version>
<Version>1.1.1</Version>
</PropertyGroup>
<!-- References -->
<ItemGroup>
<PackageReference Include="Syroot.ColoredConsole" Version="1.0.1" />
<PackageReference Include="System.IO.Pipelines" Version="4.7.2" />
<PackageReference Include="System.IO.Pipelines" Version="4.7.5" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.7.1" />
<ProjectReference Include="..\..\library\Syroot.Worms\Syroot.Worms.csproj" />
</ItemGroup>
@ -25,7 +25,7 @@
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>