From 04388e9f5155d4f1ce32edf36899bdff9c92f5d2 Mon Sep 17 00:00:00 2001 From: Belonit <54427022+Belonit@users.noreply.github.com> Date: Wed, 27 Mar 2024 14:32:13 +0300 Subject: [PATCH] Add HardEnd build option --- .github/workflows/nightly-build.yml | 8 ++ .github/workflows/pr-nightly-build.yml | 9 +++ .github/workflows/release-build.yml | 22 ++++- .gitignore | 3 + .vscode/c_cpp_properties.example.json | 2 + Spawner.props | 26 +++++- Spawner.sln | 11 ++- Spawner.vcxproj | 39 ++++----- scripts/build_debug-hardend.bat | 8 ++ scripts/build_debug.bat | 2 +- scripts/build_devbuild-hardend.bat | 8 ++ scripts/build_devbuild.bat | 2 +- scripts/build_release-hardend.bat | 8 ++ scripts/clean.bat | 4 + src/HardEndStuff/AppIcon.cpp | 16 ++++ src/HardEndStuff/Misc.cpp | 97 +++++++++++++++++++++++ src/{Spawner => HardEndStuff}/Ra2Mode.cpp | 87 ++++++++++++-------- src/{Spawner => HardEndStuff}/Ra2Mode.h | 23 +++--- src/Main.Config.h | 3 + src/Main.Ext.cpp | 27 ++++++- src/Main.Hook.cpp | 6 +- src/Main.cpp | 29 +------ src/Main.h | 6 +- src/Misc/NoCD.cpp | 29 ++++--- src/Misc/NoCD.h | 28 ------- src/Misc/VideoMode.cpp | 56 ++++++------- src/Spawner/CustomMixes.cpp | 2 +- src/Spawner/Spawner.Hook.cpp | 7 +- src/version.h | 28 +++---- 29 files changed, 396 insertions(+), 200 deletions(-) create mode 100644 scripts/build_debug-hardend.bat create mode 100644 scripts/build_devbuild-hardend.bat create mode 100644 scripts/build_release-hardend.bat create mode 100644 src/HardEndStuff/AppIcon.cpp create mode 100644 src/HardEndStuff/Misc.cpp rename src/{Spawner => HardEndStuff}/Ra2Mode.cpp (85%) rename src/{Spawner => HardEndStuff}/Ra2Mode.h (81%) delete mode 100644 src/Misc/NoCD.h 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