diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml
index 4971b231..ef11f4f9 100644
--- a/.github/workflows/nightly-build.yml
+++ b/.github/workflows/nightly-build.yml
@@ -24,3 +24,11 @@ jobs:
with:
sln-path: ${{ env.SOLUTION_PATH }}
build-config: ${{ env.BUILD_CONFIGURATION }}
+ artifact-name: compiled-dll-regular-${{ github.sha }}
+
+ - name: Build HardEnd
+ uses: ./.github/actions/build
+ with:
+ sln-path: ${{ env.SOLUTION_PATH }}
+ build-config: ${{ env.BUILD_CONFIGURATION }}-HardEnd
+ artifact-name: compiled-dll-hardend-${{ github.sha }}
diff --git a/.github/workflows/pr-nightly-build.yml b/.github/workflows/pr-nightly-build.yml
index 0ccbe7b4..a7c10bbc 100644
--- a/.github/workflows/pr-nightly-build.yml
+++ b/.github/workflows/pr-nightly-build.yml
@@ -6,6 +6,7 @@ on:
env:
SOLUTION_PATH: .
BUILD_CONFIGURATION: DevBuild
+ ARTIFACT_NAME: cncnet5_${{ github.ref_name }}.zip
jobs:
build:
@@ -21,3 +22,11 @@ jobs:
with:
sln-path: ${{ env.SOLUTION_PATH }}
build-config: ${{ env.BUILD_CONFIGURATION }}
+ artifact-name: compiled-dll-regular-${{ github.sha }}
+
+ - name: Build HardEnd
+ uses: ./.github/actions/build
+ with:
+ sln-path: ${{ env.SOLUTION_PATH }}
+ build-config: ${{ env.BUILD_CONFIGURATION }}-HardEnd
+ artifact-name: compiled-dll-hardend-${{ github.sha }}
diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml
index 97407b5e..a1afe0fc 100644
--- a/.github/workflows/release-build.yml
+++ b/.github/workflows/release-build.yml
@@ -26,14 +26,28 @@ jobs:
with:
sln-path: ${{ env.SOLUTION_PATH }}
build-config: ${{ env.BUILD_CONFIGURATION }}
+ artifact-name: compiled-dll-regular-${{ github.sha }}
+
+ - name: Build HardEnd
+ uses: ./.github/actions/build
+ with:
+ sln-path: ${{ env.SOLUTION_PATH }}
+ build-config: ${{ env.BUILD_CONFIGURATION }}-HardEnd
+ artifact-name: compiled-dll-hardend-${{ github.sha }}
- name: Create Archive For Release
run: |
mkdir ./artifact
- copy ./LICENSE.md ./artifact/LICENSE.md
- copy ./README.md ./artifact/README.md
- copy ./${{ env.BUILD_CONFIGURATION }}/cncnet5.pdb ./artifact/cncnet5.pdb
- copy ./${{ env.BUILD_CONFIGURATION }}/cncnet5.dll ./artifact/cncnet5.dll
+ mkdir ./artifact/Regular
+ copy ./LICENSE.md ./artifact/Regular/LICENSE.md
+ copy ./README.md ./artifact/Regular/README.md
+ copy ./${{ env.BUILD_CONFIGURATION }}/cncnet5.pdb ./artifact/Regular/cncnet5.pdb
+ copy ./${{ env.BUILD_CONFIGURATION }}/cncnet5.dll ./artifact/Regular/cncnet5.dll
+ mkdir ./artifact/HardEnd
+ copy ./LICENSE.md ./artifact/HardEnd/LICENSE.md
+ copy ./README.md ./artifact/HardEnd/README.md
+ copy "./${{ env.BUILD_CONFIGURATION }}-HardEnd/cncnet5.pdb" ./artifact/HardEnd/cncnet5.pdb
+ copy "./${{ env.BUILD_CONFIGURATION }}-HardEnd/cncnet5.dll" ./artifact/HardEnd/cncnet5.dll
7z a ${{ env.ARTIFACT_NAME }} ./artifact/*
- name: Upload New Release
diff --git a/.gitignore b/.gitignore
index 58ef36fc..dd9d5751 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,9 @@ yrpp-spawner-private/
Release/**
DevBuild/**
Debug/**
+Release-HardEnd/**
+DevBuild-HardEnd/**
+Debug-HardEnd/**
.vs/**
.vscode/**
diff --git a/.vscode/c_cpp_properties.example.json b/.vscode/c_cpp_properties.example.json
index 2069f247..e749a4f2 100644
--- a/.vscode/c_cpp_properties.example.json
+++ b/.vscode/c_cpp_properties.example.json
@@ -30,6 +30,8 @@
],
"defines": [
"SYR_VER=2",
+ "IS_RELEASE_VER",
+ "IS_HARDEND_VER",
"HAS_EXCEPTIONS=0",
"NOMINMAX",
"_CRT_SECURE_NO_WARNINGS",
diff --git a/Spawner.props b/Spawner.props
index 7f0b332d..c38b3b77 100644
--- a/Spawner.props
+++ b/Spawner.props
@@ -13,6 +13,18 @@
Debug
Win32
+
+ Release-HardEnd
+ Win32
+
+
+ DevBuild-HardEnd
+ Win32
+
+
+ Debug-HardEnd
+ Win32
+
@@ -67,7 +79,15 @@
$(IntDir)$(TargetName).lib
-
+
+
+ IS_HARDEND_VER;%(PreprocessorDefinitions)
+
+
+ IS_HARDEND_VER;%(PreprocessorDefinitions)
+
+
+
IS_RELEASE_VER;%(PreprocessorDefinitions)
@@ -75,7 +95,7 @@
IS_RELEASE_VER;%(PreprocessorDefinitions)
-
+
DevBuild;%(PreprocessorDefinitions)
@@ -83,7 +103,7 @@
DevBuild;%(PreprocessorDefinitions)
-
+
DEBUG;%(PreprocessorDefinitions)
Disabled
diff --git a/Spawner.sln b/Spawner.sln
index e279875c..9e0de42e 100644
--- a/Spawner.sln
+++ b/Spawner.sln
@@ -3,21 +3,30 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.32929.386
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{4A3F0CD1-23BA-4A2A-A6A2-72D7B87E0468}") = "YRpp-Spawner", "Spawner.vcxproj", "{264BD0D2-4BF7-4CFF-B33E-95A018BEA951}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "YRpp-Spawner", "Spawner.vcxproj", "{264BD0D2-4BF7-4CFF-B33E-95A018BEA951}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
+ Debug-HardEnd|x86 = Debug-HardEnd|x86
DevBuild|x86 = DevBuild|x86
+ DevBuild-HardEnd|x86 = DevBuild-HardEnd|x86
Release|x86 = Release|x86
+ Release-HardEnd|x86 = Release-HardEnd|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{264BD0D2-4BF7-4CFF-B33E-95A018BEA951}.Debug|x86.ActiveCfg = Debug|Win32
{264BD0D2-4BF7-4CFF-B33E-95A018BEA951}.Debug|x86.Build.0 = Debug|Win32
+ {264BD0D2-4BF7-4CFF-B33E-95A018BEA951}.Debug-HardEnd|x86.ActiveCfg = Debug-HardEnd|Win32
+ {264BD0D2-4BF7-4CFF-B33E-95A018BEA951}.Debug-HardEnd|x86.Build.0 = Debug-HardEnd|Win32
{264BD0D2-4BF7-4CFF-B33E-95A018BEA951}.DevBuild|x86.ActiveCfg = DevBuild|Win32
{264BD0D2-4BF7-4CFF-B33E-95A018BEA951}.DevBuild|x86.Build.0 = DevBuild|Win32
+ {264BD0D2-4BF7-4CFF-B33E-95A018BEA951}.DevBuild-HardEnd|x86.ActiveCfg = DevBuild-HardEnd|Win32
+ {264BD0D2-4BF7-4CFF-B33E-95A018BEA951}.DevBuild-HardEnd|x86.Build.0 = DevBuild-HardEnd|Win32
{264BD0D2-4BF7-4CFF-B33E-95A018BEA951}.Release|x86.ActiveCfg = Release|Win32
{264BD0D2-4BF7-4CFF-B33E-95A018BEA951}.Release|x86.Build.0 = Release|Win32
+ {264BD0D2-4BF7-4CFF-B33E-95A018BEA951}.Release-HardEnd|x86.ActiveCfg = Release-HardEnd|Win32
+ {264BD0D2-4BF7-4CFF-B33E-95A018BEA951}.Release-HardEnd|x86.Build.0 = Release-HardEnd|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Spawner.vcxproj b/Spawner.vcxproj
index 1415307d..4161a0be 100644
--- a/Spawner.vcxproj
+++ b/Spawner.vcxproj
@@ -18,41 +18,44 @@
+
-
+
+
+
+
-
+
+
+
+
-
-
-
-
-
+
+
-
-
-
+
-
-
+
+
+
@@ -61,24 +64,24 @@
-
+
+
+
-
-
-
-
+
+
-
+
\ No newline at end of file
diff --git a/scripts/build_debug-hardend.bat b/scripts/build_debug-hardend.bat
new file mode 100644
index 00000000..4307d45e
--- /dev/null
+++ b/scripts/build_debug-hardend.bat
@@ -0,0 +1,8 @@
+@if not defined _echo echo off
+
+rem Builds YRpp-Spawner Debug-HardEnd.
+
+rem Ensure we're in correct directory.
+cd /D "%~dp0"
+
+call run_msbuild /maxCpuCount /consoleloggerparameters:NoSummary /property:Configuration=Debug-HardEnd
diff --git a/scripts/build_debug.bat b/scripts/build_debug.bat
index 39ae1a8f..f7ffe946 100644
--- a/scripts/build_debug.bat
+++ b/scripts/build_debug.bat
@@ -1,6 +1,6 @@
@if not defined _echo echo off
-rem Builds YRpp-Spawner DevBuild.
+rem Builds YRpp-Spawner Debug.
rem Ensure we're in correct directory.
cd /D "%~dp0"
diff --git a/scripts/build_devbuild-hardend.bat b/scripts/build_devbuild-hardend.bat
new file mode 100644
index 00000000..125b2eb6
--- /dev/null
+++ b/scripts/build_devbuild-hardend.bat
@@ -0,0 +1,8 @@
+@if not defined _echo echo off
+
+rem Builds YRpp-Spawner DevBuild-HardEnd.
+
+rem Ensure we're in correct directory.
+cd /D "%~dp0"
+
+call run_msbuild /maxCpuCount /consoleloggerparameters:NoSummary /property:Configuration=DevBuild-HardEnd
diff --git a/scripts/build_devbuild.bat b/scripts/build_devbuild.bat
index 1b1f2803..7325716f 100644
--- a/scripts/build_devbuild.bat
+++ b/scripts/build_devbuild.bat
@@ -1,6 +1,6 @@
@if not defined _echo echo off
-rem Builds Phobos DevBuild.
+rem Builds YRpp-Spawner DevBuild.
rem Ensure we're in correct directory.
cd /D "%~dp0"
diff --git a/scripts/build_release-hardend.bat b/scripts/build_release-hardend.bat
new file mode 100644
index 00000000..42b954cd
--- /dev/null
+++ b/scripts/build_release-hardend.bat
@@ -0,0 +1,8 @@
+@if not defined _echo echo off
+
+rem Builds YRpp-Spawner Release-HardEnd.
+
+rem Ensure we're in correct directory.
+cd /D "%~dp0"
+
+call run_msbuild /maxCpuCount /consoleloggerparameters:NoSummary /property:Configuration=Release-HardEnd
diff --git a/scripts/clean.bat b/scripts/clean.bat
index 07ebbbfe..a556104e 100644
--- a/scripts/clean.bat
+++ b/scripts/clean.bat
@@ -7,4 +7,8 @@ cd /D "%~dp0"
cd ..
if exist Debug\ rmdir /S /Q Debug\
+if exist DevBuild\ rmdir /S /Q DevBuild\
if exist Release\ rmdir /S /Q Release\
+if exist Debug-HardEnd\ rmdir /S /Q Debug-HardEnd\
+if exist DevBuild-HardEnd\ rmdir /S /Q DevBuild-HardEnd\
+if exist Release-HardEnd\ rmdir /S /Q Release-HardEnd\
diff --git a/src/HardEndStuff/AppIcon.cpp b/src/HardEndStuff/AppIcon.cpp
new file mode 100644
index 00000000..a2c429b2
--- /dev/null
+++ b/src/HardEndStuff/AppIcon.cpp
@@ -0,0 +1,16 @@
+#ifdef IS_HARDEND_VER
+#include
+#include "Ra2Mode.h"
+
+HANDLE __fastcall UI_ApplyAppIcon()
+{
+ char* iconPath = Ra2Mode::IsEnabled()
+ ? "./Resources/ra2.ico"
+ : "./Resources/clienticon.ico";
+
+ return LoadImageA(NULL, iconPath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
+}
+
+DEFINE_PATCH(0x777C41, 0x90, 0x90, 0x90, 0x90); // Disable Phobos hook (0x777C41, UI_ApplyAppIcon, 0x9)
+DEFINE_JUMP(CALL, 0x777C45, GET_OFFSET(UI_ApplyAppIcon));
+#endif
diff --git a/src/HardEndStuff/Misc.cpp b/src/HardEndStuff/Misc.cpp
new file mode 100644
index 00000000..52445218
--- /dev/null
+++ b/src/HardEndStuff/Misc.cpp
@@ -0,0 +1,97 @@
+/**
+* yrpp-spawner
+*
+* Copyright(C) 2024-present CnCNet
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program.If not, see .
+*/
+
+#ifdef IS_HARDEND_VER
+#include
+#include
+#include
+
+// Skip log spam "Unable to locate scenario %s - No digest info"
+DEFINE_JUMP(LJMP, 0x69A797, 0x69A937);
+
+// Disable Ares hook AbstractTypeClass_CTOR_IDTooLong
+// Which checks type name length too aggressively
+// Use Debug::Log instead of MessageBox
+#pragma region IDTooLong
+void __fastcall IDTooLong(char* id)
+{
+ if (strlen(id) > 24)
+ Debug::Log("[Developer error] Tried to create a type with ID '%s' which is longer than the maximum length of 24.\n", id);
+}
+
+DEFINE_NAKED_HOOK(0x41088D, AbstractTypeClass_CTOR_IDTooLong)
+{
+ __asm {
+ push 24;
+ lea edx, [esp + 24h];
+ push eax;
+ push edx;
+
+ mov ecx, eax;
+ call IDTooLong;
+
+ mov ecx, 0x410895;
+ jmp ecx;
+ }
+}
+#pragma endregion IDTooLong
+
+
+// Revert Ares survivors hook
+#pragma region AresSurvivors
+DEFINE_PATCH(0x737F97, // DEFINE_HOOK(737F97, UnitClass_ReceiveDamage, 0)
+ 0x8B, 0x16, 0x8B, 0xCE, 0xFF
+);
+
+DEFINE_PATCH(0x41668B, // DEFINE_HOOK(41668B, AircraftClass_ReceiveDamage, 6)
+ 0x8B, 0x44, 0x24, 0x28, 0x8B, 0x16
+);
+#pragma endregion AresSurvivors
+
+// Revert Phobos fix "SHP debris shadows now respect the Shadow tag"
+// Disable Phobos hook Phobos_BugFixes_SHPShadowCheck
+DEFINE_PATCH(0x423365, 0x84, 0xC0, 0x0F, 0x84, 0x81, 0x00, 0x00, 0x00);
+
+// Center Pause Menu Background
+#pragma region CenterPauseMenuBackground
+#include
+#include
+
+void __fastcall InitSideRectangles_CenterBackground(
+ Surface* Surface, ConvertClass* Palette, SHPStruct* SHP, int FrameIndex,
+ const Point2D* const Position, const RectangleStruct* const Bounds, BlitterFlags Flags,
+ int Remap, int ZAdjust, ZGradient ZGradientDescIndex, int Brightness,
+ int TintColor, SHPStruct* ZShape, int ZShapeFrame, int XOffset, int YOffset
+)
+{
+ RectangleStruct shpRect = SHP->GetFrameBounds(0);
+ RectangleStruct surRect = Surface->GetRect();
+
+ Point2D nPoint {
+ (surRect.Width - 168 - shpRect.Width) >> 1 ,
+ (surRect.Height - 32 - shpRect.Height) >> 1
+ };
+
+ CC_Draw_Shape(Surface, Palette, SHP, FrameIndex, &nPoint, Bounds, Flags, Remap, ZAdjust,
+ ZGradientDescIndex, Brightness, TintColor, ZShape, ZShapeFrame, XOffset, YOffset);
+}
+
+DEFINE_JUMP(CALL, 0x72F624, GET_OFFSET(InitSideRectangles_CenterBackground));
+#pragma endregion CenterPauseMenuBackground
+#endif
diff --git a/src/Spawner/Ra2Mode.cpp b/src/HardEndStuff/Ra2Mode.cpp
similarity index 85%
rename from src/Spawner/Ra2Mode.cpp
rename to src/HardEndStuff/Ra2Mode.cpp
index 8665644a..1412f74b 100644
--- a/src/Spawner/Ra2Mode.cpp
+++ b/src/HardEndStuff/Ra2Mode.cpp
@@ -17,8 +17,8 @@
* along with this program.If not, see .
*/
+#ifdef IS_HARDEND_VER
#include "Ra2Mode.h"
-
#include
#include
#include
@@ -29,11 +29,16 @@
bool Ra2Mode::Enabled = false;
-void Ra2Mode::Apply()
+DEFINE_HOOK(0x6BD7CB, WinMain_Ra2ModePatches, 0x5)
{
- if (Ra2Mode::Enabled)
- return;
+ if (Ra2Mode::IsNeedToApply())
+ Ra2Mode::Apply();
+
+ return 0;
+}
+void Ra2Mode::Apply()
+{
Ra2Mode::Enabled = true;
// Window title
@@ -59,6 +64,24 @@ void Ra2Mode::Apply()
Patch::Apply_LJMP(0x553686, 0x553686 + 6);
{ // Allows to detect disguise units with Psychic Sensor
+
+ // This is a very dirty hack that changes the behavior of the SensorArray logic re-implemented in Ares
+ // The SensorArray logic works with the SensorsOfHouses array, and here we additionally process the DisguiseSensorsOfHouses array
+ struct DetectDisguiseHack
+ {
+ static void __fastcall Sensors_AddOfHouse(CellClass* pThis, void*, unsigned int idx)
+ {
+ pThis->Sensors_AddOfHouse(idx);
+ pThis->DisguiseSensors_AddOfHouse(idx);
+ }
+
+ static void __fastcall Sensors_RemOfHouse(CellClass* pThis, void*, unsigned int idx)
+ {
+ pThis->Sensors_RemOfHouse(idx);
+ pThis->DisguiseSensors_RemOfHouse(idx);
+ }
+ };
+
Patch::Apply_CALL(0x45591E, GET_OFFSET(DetectDisguiseHack::Sensors_AddOfHouse));
Patch::Apply_CALL(0x4557B7, GET_OFFSET(DetectDisguiseHack::Sensors_RemOfHouse));
@@ -134,7 +157,7 @@ bool Ra2Mode::IsNeedToApply()
{
auto const pConfig = Spawner::GetConfig();
- return (pConfig->Ra2Mode
+ return Spawner::Enabled && (pConfig->Ra2Mode
|| (pConfig->LoadSaveGame && Ra2Mode::CheckSaveGameID(pConfig->SaveGameName))
|| (pConfig->IsCampaign && strstr(pConfig->ScenarioName, "RA2->"))
);
@@ -155,24 +178,6 @@ bool Ra2Mode::CheckSaveGameID(const char* saveGameName)
return false;
}
-// Allows to detect disguise units with Psychic Sensor
-#pragma region DetectDisguiseHack
-
-// This is a very dirty hack that changes the behavior of the SensorArray logic re-implemented in Ares
-// The SensorArray logic works with the SensorsOfHouses array, and here we additionally process the DisguiseSensorsOfHouses array
-void __fastcall Ra2Mode::DetectDisguiseHack::Sensors_AddOfHouse(CellClass* pThis, void*, unsigned int idx)
-{
- pThis->Sensors_AddOfHouse(idx);
- pThis->DisguiseSensors_AddOfHouse(idx);
-}
-
-void __fastcall Ra2Mode::DetectDisguiseHack::Sensors_RemOfHouse(CellClass* pThis, void*, unsigned int idx)
-{
- pThis->Sensors_RemOfHouse(idx);
- pThis->DisguiseSensors_RemOfHouse(idx);
-}
-#pragma endregion DetectDisguiseHack
-
// Allow allies to repair on service depot
DEFINE_HOOK(0x700594, TechnoClass_WhatAction__AllowAlliesRepair, 0x5)
{
@@ -199,6 +204,24 @@ DEFINE_HOOK(0x700594, TechnoClass_WhatAction__AllowAlliesRepair, 0x5)
namespace RepairFlyMZone
{
UnitTypeClass* pUnitType = nullptr;
+
+ void Prefix(UnitClass* pThis)
+ {
+ if (pThis->Type->MovementZone == MovementZone::Fly)
+ {
+ pUnitType = pThis->Type;
+ pUnitType->MovementZone = MovementZone::Normal;
+ }
+ }
+
+ void Suffix()
+ {
+ if (pUnitType)
+ {
+ pUnitType->MovementZone = MovementZone::Fly;
+ pUnitType = nullptr;
+ }
+ }
}
DEFINE_HOOK_AGAIN(0x740006, UnitClass_WhatAction__AllowRepairFlyMZone_Prefix, 0x5)
@@ -208,14 +231,10 @@ DEFINE_HOOK(0x74012A, UnitClass_WhatAction__AllowRepairFlyMZone_Prefix, 0x6)
? 0
: 0x740130;
- if (!Ra2Mode::IsEnabled())
- return returnAddress;
-
- GET(UnitClass*, pThis, ESI);
- if (pThis->Type->MovementZone == MovementZone::Fly)
+ if (Ra2Mode::IsEnabled())
{
- RepairFlyMZone::pUnitType = pThis->Type;
- RepairFlyMZone::pUnitType->MovementZone = MovementZone::Normal;
+ GET(UnitClass*, pThis, ESI);
+ RepairFlyMZone::Prefix(pThis);
}
return returnAddress;
@@ -223,11 +242,7 @@ DEFINE_HOOK(0x74012A, UnitClass_WhatAction__AllowRepairFlyMZone_Prefix, 0x6)
DEFINE_HOOK(0x7401C1, UnitClass_WhatAction__AllowRepairFlyMZone_Suffix, 0x6)
{
- if (RepairFlyMZone::pUnitType)
- {
- RepairFlyMZone::pUnitType->MovementZone = MovementZone::Fly;
- RepairFlyMZone::pUnitType = nullptr;
- }
+ RepairFlyMZone::Suffix();
return 0;
}
@@ -274,3 +289,5 @@ DEFINE_HOOK(0x71F1A2, TEventClass_Execute_AllDestroyed, 0x6)
return AllDestroyed;
}
+
+#endif
diff --git a/src/Spawner/Ra2Mode.h b/src/HardEndStuff/Ra2Mode.h
similarity index 81%
rename from src/Spawner/Ra2Mode.h
rename to src/HardEndStuff/Ra2Mode.h
index bd070396..1eeaab29 100644
--- a/src/Spawner/Ra2Mode.h
+++ b/src/HardEndStuff/Ra2Mode.h
@@ -18,24 +18,29 @@
*/
#pragma once
-class CellClass;
+#ifdef IS_HARDEND_VER
class Ra2Mode
{
static bool Enabled;
-public:
- static bool IsEnabled()
- {
- return Ra2Mode::Enabled;
- };
+public:
static void Apply();
static bool IsNeedToApply();
static bool CheckSaveGameID(const char* saveGameName);
- struct DetectDisguiseHack
+ static bool IsEnabled()
+ {
+ return Ra2Mode::Enabled;
+ };
+};
+#else
+class Ra2Mode
+{
+public:
+ static bool IsEnabled()
{
- static void __fastcall Sensors_AddOfHouse(CellClass* pThis, void*, unsigned int idx);
- static void __fastcall Sensors_RemOfHouse(CellClass* pThis, void*, unsigned int idx);
+ return false;
};
};
+#endif
diff --git a/src/Main.Config.h b/src/Main.Config.h
index d065b78d..a8e0d1f3 100644
--- a/src/Main.Config.h
+++ b/src/Main.Config.h
@@ -23,6 +23,7 @@ class MainConfig
public:
bool MPDebug;
bool DumpTypes;
+ bool NoCD;
int RA2ModeSaveID;
bool SingleProcAffinity;
@@ -45,6 +46,8 @@ class MainConfig
MainConfig()
: MPDebug { false }
, DumpTypes { false }
+ , NoCD { false }
+ , RA2ModeSaveID { 0 }
, SingleProcAffinity { true }
, DisableEdgeScrolling { false }
diff --git a/src/Main.Ext.cpp b/src/Main.Ext.cpp
index 7dc864d8..0b1f997b 100644
--- a/src/Main.Ext.cpp
+++ b/src/Main.Ext.cpp
@@ -33,7 +33,32 @@ const char Main::readDelims[4] = ",";
#include
#include
-bool Main::DetachFromDebugger()
+void Main::DetachFromDebugger()
+{
+ if (Main::TryDetachFromDebugger())
+ {
+ MessageBoxW(NULL,
+ L"You can now attach a debugger.\n\n"
+
+ L"Press OK to continue YR execution.",
+ L"Debugger Notice", MB_OK);
+ }
+ else
+ {
+ MessageBoxW(NULL,
+ L"You can now attach a debugger.\n\n"
+
+ L"To attach a debugger find the YR process in Process Hacker "
+ L"/ Visual Studio processes window and detach debuggers from it, "
+ L"then you can attach your own debugger. After this you should "
+ L"terminate Syringe.exe because it won't automatically exit when YR is closed.\n\n"
+
+ L"Press OK to continue YR execution.",
+ L"Debugger Notice", MB_OK);
+ }
+}
+
+bool Main::TryDetachFromDebugger()
{
auto GetDebuggerProcessId = [](DWORD dwSelfProcessId) -> DWORD
{
diff --git a/src/Main.Hook.cpp b/src/Main.Hook.cpp
index 05f32b13..c0e0be77 100644
--- a/src/Main.Hook.cpp
+++ b/src/Main.Hook.cpp
@@ -23,15 +23,15 @@
bool __stdcall DllMain(HANDLE hInstance, DWORD dwReason, LPVOID v)
{
if (dwReason == DLL_PROCESS_ATTACH)
- {
Main::hInstance = hInstance;
- }
+
return true;
}
DEFINE_HOOK(0x7CD810, ExeRun, 0x9)
{
Main::ExeRun();
+
return 0;
}
@@ -41,6 +41,7 @@ DEFINE_HOOK(0x52F639, ParseCommandLine, 0x5)
GET(int, nNumArgs, EDI);
Main::CmdLineParse(ppArgs, nNumArgs);
+
return 0;
}
@@ -48,5 +49,6 @@ DEFINE_HOOK(0x6BC0D7, WinMain_LoadSettings, 0x5)
{
Main::GetConfig()->LoadFromINIFile();
Main::GetConfig()->ApplyStaticOptions();
+
return 0;
}
diff --git a/src/Main.cpp b/src/Main.cpp
index a14d9f08..69495b9c 100644
--- a/src/Main.cpp
+++ b/src/Main.cpp
@@ -23,7 +23,6 @@
#include
#include
-#include
HANDLE Main::hInstance = nullptr;
std::unique_ptr Main::Config = std::make_unique();
@@ -31,29 +30,8 @@ std::unique_ptr Main::Config = std::make_unique();
void Main::ExeRun()
{
Patch::ApplyStatic();
-
#ifdef DEBUG
- if (Main::DetachFromDebugger())
- {
- MessageBoxW(NULL,
- L"You can now attach a debugger.\n\n"
-
- L"Press OK to continue YR execution.",
- L"Debugger Notice", MB_OK);
- }
- else
- {
- MessageBoxW(NULL,
- L"You can now attach a debugger.\n\n"
-
- L"To attach a debugger find the YR process in Process Hacker "
- L"/ Visual Studio processes window and detach debuggers from it, "
- L"then you can attach your own debugger. After this you should "
- L"terminate Syringe.exe because it won't automatically exit when YR is closed.\n\n"
-
- L"Press OK to continue YR execution.",
- L"Debugger Notice", MB_OK);
- }
+ Main::DetachFromDebugger();
#endif
}
@@ -68,11 +46,10 @@ void Main::CmdLineParse(char** ppArgs, int nNumArgs)
if (0 == _stricmp(pArg, "-CD"))
{
- NoCD::Apply();
+ Main::Config->NoCD = true;
}
else if (0 == _stricmp(pArg, "-SPAWN"))
{
- NoCD::Apply();
Spawner::Enabled = true;
}
else if (0 == _stricmp(pArg, "-DumpTypes"))
@@ -84,6 +61,4 @@ void Main::CmdLineParse(char** ppArgs, int nNumArgs)
Main::Config->RA2ModeSaveID = strtoul(pArg - 1 + sizeof("-RA2ModeSaveID="), 0, 0);
}
}
-
- NoCD::InitNoCDMode();
}
diff --git a/src/Main.h b/src/Main.h
index 142c5460..dce17322 100644
--- a/src/Main.h
+++ b/src/Main.h
@@ -33,14 +33,13 @@ class Main
public:
static void ExeRun();
- static void CmdLineParse(char**, int);
+ static void CmdLineParse(char** ppArgs, int nNumArgs);
static MainConfig* GetConfig()
{
return Config.get();
}
- // variables
static HANDLE hInstance;
static const size_t readLength = 2048;
@@ -49,6 +48,7 @@ class Main
static const char readDelims[4];
#ifdef DEBUG
- static bool DetachFromDebugger();
+ static void DetachFromDebugger();
+ static bool TryDetachFromDebugger();
#endif
};
diff --git a/src/Misc/NoCD.cpp b/src/Misc/NoCD.cpp
index ef973f3d..489d8144 100644
--- a/src/Misc/NoCD.cpp
+++ b/src/Misc/NoCD.cpp
@@ -17,11 +17,11 @@
* along with this program.If not, see .
*/
-#include "NoCD.h"
-#include
-
-#include
+#include
+#include
#include
+#include
+#include
#include
// Based on https://github.com/Ares-Developers/Ares/blob/4f1d929920aca31924c6cd4d3dfa849daa65252a/src/Misc/CopyProtection.cpp
@@ -29,13 +29,8 @@
// and https://github.com/Ares-Developers/Ares/blob/4f1d929920aca31924c6cd4d3dfa849daa65252a/src/Ares.cpp#L323
// and https://github.com/CnCNet/yr-patches/blob/1f2a00de8226823952763fa411aa5e75dbb4012a/src/no-cd.asm
-bool NoCD::Enabled = false;
-
-void NoCD::Apply()
+void ApplyNoCDPatches()
{
- if (NoCD::Enabled)
- return;
-
Patch::Apply_RAW(0x4A80D0, // GetCDIndex
{
0xB8, 0x02, 0x00, 0x00, 0x00, // mov eax, 2
@@ -85,15 +80,19 @@ void NoCD::Apply()
break;
}
}
-
- NoCD::Enabled = true;
};
-void NoCD::InitNoCDMode()
+DEFINE_HOOK(0x6BD7CB, WinMain_NoCDPatches, 0x5)
{
- if (!GetCDClass::Instance->Count)
+ if (Spawner::Enabled || Main::GetConfig()->NoCD)
+ {
+ ApplyNoCDPatches();
+ }
+ else if (!GetCDClass::Instance->Count)
{
Debug::Log("[Spawner] No CD drives detected. Switching to NoCD mode.\n");
- NoCD::Apply();
+ ApplyNoCDPatches();
}
+
+ return 0;
}
diff --git a/src/Misc/NoCD.h b/src/Misc/NoCD.h
deleted file mode 100644
index ccbb0303..00000000
--- a/src/Misc/NoCD.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
-* yrpp-spawner
-*
-* Copyright(C) 2022-present CnCNet
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program.If not, see .
-*/
-
-#pragma once
-
-class NoCD
-{
-public:
- static bool Enabled;
- static void Apply();
- static void InitNoCDMode();
-};
diff --git a/src/Misc/VideoMode.cpp b/src/Misc/VideoMode.cpp
index d52ef1ee..acd0fda5 100644
--- a/src/Misc/VideoMode.cpp
+++ b/src/Misc/VideoMode.cpp
@@ -22,6 +22,31 @@
#include
#include
+DEFINE_HOOK(0x6BD7CB, WinMain_VideoModePatches, 0x5)
+{
+ if (Spawner::Enabled)
+ {
+ // allow hires modes
+ Patch::Apply_LJMP(0x56017A, 0x560183); // OptionsDlg_WndProc_RemoveResLimit
+
+ // skip the allowhires check entirely - all supported 16bit modes are accepted
+ Patch::Apply_LJMP(0x5601E3, 0x5601FC); // OptionsDlg_WndProc_RemoveHiResCheck
+
+ // Fixes the layout for some screen resolutions, for example 1152x648
+ Patch::Apply_TYPED(0x72ECA6, { 600 /* original = 768 */ });
+
+ // This will force the game to always use ddraw's blit function rather than WW blit
+ // We're avoiding ww blit functions because they are not thread safe
+ Patch::Apply_RAW(0x4BB1FE, { 0 }); // DSurface::Blit_Clip
+
+ // Disables drawing the menu bg which pops up on loading
+ Patch::Apply_LJMP(0x7782B7, 0x7782C4); // Load_Title_Screen
+ Patch::Apply_LJMP(0x52FF4A, 0x52FF57); // Redraw_Surface
+ }
+
+ return 0;
+}
+
DEFINE_HOOK(0x6BC14D, WinMain_ReadScreenResolutionFromIni, 0x5)
{
if (!Spawner::Enabled)
@@ -56,6 +81,7 @@ DEFINE_HOOK(0x640CE2, PreviewClass_DrawMap, 0x5)
R->ECX(Top);
R->EDX(Width);
R->ESI(Height);
+
return 0x640D36;
}
@@ -76,15 +102,6 @@ DEFINE_HOOK(0x60C43B, EnumChildProc_60C0C0, 0x5)
return 0x60C443;
}
-// allow hires modes
-DEFINE_JUMP(LJMP, 0x56017A, 0x560183) // OptionsDlg_WndProc_RemoveResLimit
-
-// skip the allowhires check entirely - all supported 16bit modes are accepted
-DEFINE_JUMP(LJMP, 0x5601E3, 0x5601FC) // OptionsDlg_WndProc_RemoveHiResCheck
-
-// Fixes the layout for some screen resolutions, for example 1152x648
-DEFINE_PATCH_TYPED(WORD, 0x72ECA6, 600 /*original = 768*/);
-
// Cap the sidebar height to 1376 pixels
DEFINE_HOOK(0x6A518E, SidebarClass_InitGUI, 0x5)
{
@@ -94,24 +111,3 @@ DEFINE_HOOK(0x6A518E, SidebarClass_InitGUI, 0x5)
return 0;
}
-
-// This will force the game to always use ddraw's blit function rather than WW blit
-// We're avoiding ww blit functions because they are not thread safe
-DEFINE_PATCH(0x4BB1FE, 0); // DSurface::Blit_Clip
-
-// Disables drawing the menu bg which pops up on loading
-#pragma region SkipsMenuBackground
-DEFINE_HOOK(0x7782B7, Load_Title_Screen, 0x6)
-{
- return Spawner::Enabled
- ? 0x7782C4
- : 0;
-}
-
-DEFINE_HOOK(0x52FF4A, Redraw_Surface, 0x6)
-{
- return Spawner::Enabled
- ? 0x52FF57
- : 0;
-}
-#pragma endregion SkipsMenuBackground
diff --git a/src/Spawner/CustomMixes.cpp b/src/Spawner/CustomMixes.cpp
index cb475137..52b6fe39 100644
--- a/src/Spawner/CustomMixes.cpp
+++ b/src/Spawner/CustomMixes.cpp
@@ -17,7 +17,7 @@
* along with this program.If not, see .
*/
-#include "Ra2Mode.h"
+#include
#include
#include
diff --git a/src/Spawner/Spawner.Hook.cpp b/src/Spawner/Spawner.Hook.cpp
index dc12b780..f120bd60 100644
--- a/src/Spawner/Spawner.Hook.cpp
+++ b/src/Spawner/Spawner.Hook.cpp
@@ -19,23 +19,18 @@
#include "Spawner.h"
#include "NetHack.h"
-#include "Ra2Mode.h"
#include
#include
#include
#include
-DEFINE_HOOK(0x6BD7CB, WinMain_SpawnerInit, 0x5)
+DEFINE_HOOK(0x6BD7C5, WinMain_SpawnerInit, 0x6)
{
if (Spawner::Enabled)
{
Spawner::Init();
- if (Ra2Mode::IsNeedToApply())
- {
- Ra2Mode::Apply();
- }
Patch::Apply_CALL(0x48CDD3, Spawner::StartGame); // Main_Game
Patch::Apply_CALL(0x48CFAA, Spawner::StartGame); // Main_Game
diff --git a/src/version.h b/src/version.h
index f912d827..da7d33d8 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1,37 +1,35 @@
#ifndef VERSION_H
#define VERSION_H
-#ifdef IS_ANTICHEAT_VER
- #define PRODUCT_NAME "YRpp-Spawner (AntiCheat)"
-#else
- #define PRODUCT_NAME "YRpp-Spawner"
-#endif
-
-#define FILE_DESCRIPTION "CnCNet5: Spawner"
-
#define _WSTR(x) _WSTR_(x)
#define _WSTR_(x) L ## #x
#define _STR(x) _STR_(x)
#define _STR_(x) #x
-#pragma region Release build version numbering
+// Build number. Incremented on each released build
+#define BUILD_NUMBER 2
// Indicates project maturity and completeness
#define VERSION_MAJOR 0
-
// Indicates major changes and significant additions, like new logics
#define VERSION_MINOR 0
-
// Indicates minor changes, like vanilla bugfixes, unhardcodings or hacks
#define VERSION_REVISION 0
-
// Indicates YRpp-Spawner-related bugfixes only
#define VERSION_PATCH 2
-#pragma endregion
+#if defined(IS_ANTICHEAT_VER) && defined(IS_HARDEND_VER)
+ #define PRODUCT_TYPE "(HardEnd + AntiCheat)"
+#elif !defined(IS_ANTICHEAT_VER) && defined(IS_HARDEND_VER)
+ #define PRODUCT_TYPE "(HardEnd)"
+#elif defined(IS_ANTICHEAT_VER) && !defined(IS_HARDEND_VER)
+ #define PRODUCT_TYPE "(AntiCheat)"
+#else
+ #define PRODUCT_TYPE "(Regular)"
+#endif
-// Build number. Incremented on each released build.
-#define BUILD_NUMBER 2
+#define PRODUCT_NAME "YRpp-Spawner " PRODUCT_TYPE
+#define FILE_DESCRIPTION "CnCNet5: Spawner " PRODUCT_TYPE
// Nightly defines GIT_COMMIT and GIT_BRANCH in GH Actions