diff --git a/codxe.vcxproj b/codxe.vcxproj index 01a54a1..08e2351 100644 --- a/codxe.vcxproj +++ b/codxe.vcxproj @@ -80,9 +80,13 @@ + + + + @@ -148,7 +152,7 @@ - + @@ -184,11 +188,15 @@ + + + + diff --git a/src/game/iw2/mp/components/project_velocity.cpp b/src/game/iw2/mp/components/project_velocity.cpp new file mode 100644 index 0000000..766046d --- /dev/null +++ b/src/game/iw2/mp/components/project_velocity.cpp @@ -0,0 +1,97 @@ +#include "pch.h" +#include "project_velocity.h" +#include + +namespace iw2 { +namespace mp { + +// Global detour object +Detour PM_ProjectVelocity_Detour; + +const uint32_t NOP_INST = 0x60000000; + +// The Hook function that the Detour will point to +void PM_ProjectVelocity_Hook(vec3_t in, vec3_t normal, vec3_t out) +{ + const float EPSILON = 0.001f; + float normalZ = normal[2]; + float speedXY = (in[0] * in[0]) + (in[1] * in[1]); + + if (normalZ < EPSILON || speedXY <= 0.0f) { + out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; + return; + } + + float dotNormalXY = (in[0] * normal[0]) + (in[1] * normal[1]); + float projRatio = -dotNormalXY / normalZ; + float projSq = (in[2] * in[2]) + speedXY; + float divisor = speedXY + (projRatio * projRatio); + + if (divisor > 0.0f) { + float scale = sqrtf(projSq / divisor); + // FIXED: Added logical OR operators + if (scale < 1.0f || projRatio < 0.0f || in[2] > 0.0f) { + out[0] = in[0] * scale; + out[1] = in[1] * scale; + out[2] = projRatio * scale; + return; + } + } + + out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; +} + +// Simple helper to build the branch-link (bl) instruction +static uint32_t make_bl(uint32_t current, uint32_t target) { + uint32_t li = (target - current) & 0x03FFFFFC; + return (18u << 26) | li | 1u; +} + +// Simple helper to build the unconditional branch (b) instruction +static uint32_t make_b(uint32_t current, uint32_t target) { + uint32_t li = (target - current) & 0x03FFFFFC; + return (18u << 26) | li; +} + +void project_velocity::install_patch() { + // 1. NOP out the original call to the dummy function + *(volatile uint32_t*)PV_Config::CallToDummyAddr = NOP_INST; + + // 2. Initialize the Detour on the DummyAddr + // This redirects any call to DummyAddr to our PM_ProjectVelocity_Hook + PM_ProjectVelocity_Detour = Detour(reinterpret_cast(PV_Config::DummyAddr), reinterpret_cast(PM_ProjectVelocity_Hook)); + PM_ProjectVelocity_Detour.Install(); + + // 3. Write the inline argument setup and call at PatchAddr + volatile uint32_t* patch = (volatile uint32_t*)PV_Config::PatchAddr; + + // Setup Arguments + patch[0] = 0x7FE3FB78; // mr r3, r31 + patch[1] = 0x388100A4; // addi r4, r1, 0xA4 + patch[2] = 0x7FE5FB78; // mr r5, r31 + + // Call the hooked DummyAddr (where our Detour is waiting) + uint32_t blAddr = PV_Config::PatchAddr + (3 * 4); + patch[3] = make_bl(blAddr, PV_Config::DummyAddr); + + // Jump past the rest of the original logic (18 instructions total) + uint32_t bAddr = PV_Config::PatchAddr + (4 * 4); + uint32_t targetAddr = PV_Config::PatchAddr + (18 * 4); + patch[4] = make_b(bAddr, targetAddr); + + // Clear the remaining original instructions + for (int i = 5; i < 18; i++) { + patch[i] = NOP_INST; + } +} + +project_velocity::project_velocity() { + install_patch(); +} + +project_velocity::~project_velocity() { + PM_ProjectVelocity_Detour.Remove(); +} + +} // namespace mp +} // namespace iw2 \ No newline at end of file diff --git a/src/game/iw2/mp/components/project_velocity.h b/src/game/iw2/mp/components/project_velocity.h new file mode 100644 index 0000000..15c7274 --- /dev/null +++ b/src/game/iw2/mp/components/project_velocity.h @@ -0,0 +1,31 @@ +#pragma once +#include "pch.h" + +namespace iw2 { +namespace mp { + + typedef float vec_t; + typedef vec_t vec3_t[3]; + + namespace PV_Config { + static const uint32_t PatchAddr = 0x8248B178; // Location where we should call our dummy function + static const uint32_t DummyAddr = 0x824550B8; // In COD2 there is no call to clip_velocity so we will use a dummy function address (and hook to it) + static const uint32_t CallToDummyAddr = 0x82455F74; // Location of calls to unused function + } + typedef float vec3_t[3]; + // Forward declaration using float* to avoid array-size decay errors + void PM_ProjectVelocity_Hook(vec3_t in, vec3_t normal, vec3_t out); + + class project_velocity : public Module { + public: + project_velocity(); + virtual ~project_velocity(); + + private: + void install_patch(); + project_velocity(const project_velocity&); + project_velocity& operator=(const project_velocity&); + }; + +} // namespace mp +} // namespace iw2 \ No newline at end of file diff --git a/src/game/iw2/mp/main.cpp b/src/game/iw2/mp/main.cpp index 827f597..89a8b2f 100644 --- a/src/game/iw2/mp/main.cpp +++ b/src/game/iw2/mp/main.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "components/g_scr_main.h" #include "components/scr_parser.h" +#include "components/project_velocity.h" #include "main.h" namespace iw2 @@ -14,6 +15,7 @@ IW2_MP_Plugin::IW2_MP_Plugin() RegisterModule(new Config()); RegisterModule(new g_scr_main()); RegisterModule(new scr_parser()); + RegisterModule(new project_velocity()); } IW2_MP_Plugin::~IW2_MP_Plugin() diff --git a/src/game/ngl/mp/components/project_velocity.cpp b/src/game/ngl/mp/components/project_velocity.cpp new file mode 100644 index 0000000..5439219 --- /dev/null +++ b/src/game/ngl/mp/components/project_velocity.cpp @@ -0,0 +1,80 @@ +#include "pch.h" +#include "project_velocity.h" +#include + +namespace ngl { +namespace mp { + +// Global detour object +Detour PM_ProjectVelocity_Detour; + +const uint32_t NOP_INST = 0x60000000; + +// The Hook function that the Detour will point to +void PM_ProjectVelocity_Hook(vec3_t in, vec3_t normal, vec3_t out) +{ + const float EPSILON = 0.001f; + float normalZ = normal[2]; + float speedXY = (in[0] * in[0]) + (in[1] * in[1]); + + if (normalZ < EPSILON || speedXY <= 0.0f) { + out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; + return; + } + + float dotNormalXY = (in[0] * normal[0]) + (in[1] * normal[1]); + float projRatio = -dotNormalXY / normalZ; + float projSq = (in[2] * in[2]) + speedXY; + float divisor = speedXY + (projRatio * projRatio); + + if (divisor > 0.0f) { + float scale = sqrtf(projSq / divisor); + // FIXED: Added logical OR operators + if (scale < 1.0f || projRatio < 0.0f || in[2] > 0.0f) { + out[0] = in[0] * scale; + out[1] = in[1] * scale; + out[2] = projRatio * scale; + return; + } + } + + out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; +} + +// Simple helper to build the branch-link (bl) instruction +static uint32_t make_bl(uint32_t current, uint32_t target) { + uint32_t li = (target - current) & 0x03FFFFFC; + return (18u << 26) | li | 1u; +} + +// Simple helper to build the unconditional branch (b) instruction +//static uint32_t make_b(uint32_t current, uint32_t target) { +// uint32_t li = (target - current) & 0x03FFFFFC; +// return (18u << 26) | li; +//} + +void project_velocity::install_patch() { + // 1. NOP out the original call to the dummy function + *(volatile uint32_t*)PV_Config::CallToDummyAddr = NOP_INST; + + // 2. Initialize the Detour on the DummyAddr + // This redirects any call to DummyAddr to our PM_ProjectVelocity_Hook + PM_ProjectVelocity_Detour = Detour(reinterpret_cast(PV_Config::DummyAddr), reinterpret_cast(PM_ProjectVelocity_Hook)); + PM_ProjectVelocity_Detour.Install(); + + // 3. Write the inline argument setup and call at PatchAddr + volatile uint32_t* patch = (volatile uint32_t*)PV_Config::PatchAddr; + + patch[0] = make_bl(PV_Config::PatchAddr, PV_Config::DummyAddr); +} + +project_velocity::project_velocity() { + install_patch(); +} + +project_velocity::~project_velocity() { + PM_ProjectVelocity_Detour.Remove(); +} + +} // namespace mp +} // namespace ngl \ No newline at end of file diff --git a/src/game/ngl/mp/components/project_velocity.h b/src/game/ngl/mp/components/project_velocity.h new file mode 100644 index 0000000..94e8fdf --- /dev/null +++ b/src/game/ngl/mp/components/project_velocity.h @@ -0,0 +1,31 @@ +#pragma once +#include "pch.h" + +namespace ngl { +namespace mp { + + typedef float vec_t; + typedef vec_t vec3_t[3]; + + namespace PV_Config { + static const uint32_t PatchAddr = 0x8246E1E0; // Location where we should call our dummy function + static const uint32_t DummyAddr = 0x8244C1C8; // In COD2 there is no call to clip_velocity so we will use a dummy function address (and hook to it) + static const uint32_t CallToDummyAddr = 0x82466704; // Location of calls to unused function + } + typedef float vec3_t[3]; + // Forward declaration using float* to avoid array-size decay errors + void PM_ProjectVelocity_Hook(vec3_t in, vec3_t normal, vec3_t out); + + class project_velocity : public Module { + public: + project_velocity(); + virtual ~project_velocity(); + + private: + void install_patch(); + project_velocity(const project_velocity&); + project_velocity& operator=(const project_velocity&); + }; + +} // namespace mp +} // namespace ngl \ No newline at end of file diff --git a/src/game/ngl/mp/main.cpp b/src/game/ngl/mp/main.cpp new file mode 100644 index 0000000..25fbf3b --- /dev/null +++ b/src/game/ngl/mp/main.cpp @@ -0,0 +1,24 @@ +#include "pch.h" +#include "main.h" +#include "components/project_velocity.h" + +namespace ngl +{ +namespace mp +{ + +NGL_MP_Plugin::NGL_MP_Plugin() +{ + DbgPrint("NGL MP Plugin initialized\n"); + + //install_patch(); + RegisterModule(new project_velocity()); +} + +NGL_MP_Plugin::~NGL_MP_Plugin() +{ + DbgPrint("NGL MP Plugin shutting down\n"); +} + +} // namespace mp +} // namespace ngl \ No newline at end of file diff --git a/src/game/ngl/mp/main.h b/src/game/ngl/mp/main.h new file mode 100644 index 0000000..dbab00c --- /dev/null +++ b/src/game/ngl/mp/main.h @@ -0,0 +1,17 @@ +#pragma once + +#include "plugin.h" + +namespace ngl +{ +namespace mp +{ +class NGL_MP_Plugin : public Plugin +{ + + public: + NGL_MP_Plugin(); + ~NGL_MP_Plugin(); +}; +} // namespace mp +} // namespace ngl diff --git a/src/pch.h b/src/pch.h index c420dc1..f07dab0 100644 --- a/src/pch.h +++ b/src/pch.h @@ -44,6 +44,8 @@ #include "common/branding.h" #include "common/config.h" +#include "game/ngl/mp/main.h" + // IW2-specific includes #include "game/iw2/sp/main.h" #include "game/iw2/sp/structs.h" diff --git a/src/plugin_manager.cpp b/src/plugin_manager.cpp index 49123da..caa49db 100644 --- a/src/plugin_manager.cpp +++ b/src/plugin_manager.cpp @@ -146,6 +146,14 @@ const GameInfo GAME_INFO[] = { "Call of Duty: Modern Warfare 3 MP Title Update #24", &CreatePlugin, }, + { + 0x415607E1, + 0x45B56A5C,// Mon Jan 22 20 : 52 : 28 2007 + "codmp_xenonf.xex", + "NGL MP TU3", + "Call of Duty: 3 Title Update #3", + &CreatePlugin, + }, }; const GameInfo *FindGameInfo(DWORD title_id, DWORD timestamp) diff --git a/src/version.h b/src/version.h index 2078852..2e59f06 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ // Auto-generated version header #pragma once -#define BUILD_NUMBER 0 +#define BUILD_NUMBER 249