Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion codxe.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,13 @@

<ClCompile Include="src\common\config.cpp" />

<ClCompile Include="src\game\ngl\mp\main.cpp" />
<ClCompile Include="src\game\ngl\mp\components\project_velocity.cpp" />

<ClCompile Include="src\game\iw2\sp\components\scr_parser.cpp" />
<ClCompile Include="src\game\iw2\sp\main.cpp" />

<ClCompile Include="src\game\iw2\mp\components\project_velocity.cpp" />
<ClCompile Include="src\game\iw2\mp\components\g_scr_main.cpp" />
<ClCompile Include="src\game\iw2\mp\components\scr_parser.cpp" />
<ClCompile Include="src\game\iw2\mp\main.cpp" />
Expand Down Expand Up @@ -148,7 +152,7 @@

<ClCompile Include="src\game\t4\sp\components\clipmap.cpp" />
<ClCompile Include="src\game\t4\sp\components\g_scr_mover.cpp" />
<ClCompile Include="src\game\t4\sp\components\g_client_fields.cpp" />
<ClCompile Include="src\game\t4\sp\components\g_client_fields.cpp" />
<ClCompile Include="src\game\t4\sp\components\g_client_script_cmd.cpp" />
<ClCompile Include="src\game\t4\sp\components\g_scr_main.cpp" />
<ClCompile Include="src\game\t4\sp\components\scr_parser.cpp" />
Expand Down Expand Up @@ -184,11 +188,15 @@
<ClInclude Include="src\common\branding.h" />
<ClInclude Include="src\common\config.h" />

<ClInclude Include="src\game\ngl\mp\main.h" />
<ClInclude Include="src\game\ngl\mp\components\project-velocity.h" />

<ClInclude Include="src\game\iw2\sp\components\scr_parser.h" />
<ClInclude Include="src\game\iw2\sp\main.h" />
<ClInclude Include="src\game\iw2\sp\structs.h" />
<ClInclude Include="src\game\iw2\sp\symbols.h" />

<ClInclude Include="src\game\iw2\mp\components\project_velocity.h" />
<ClInclude Include="src\game\iw2\mp\components\scr_parser.h" />
<ClInclude Include="src\game\iw2\mp\main.h" />
<ClInclude Include="src\game\iw2\mp\structs.h" />
Expand Down
97 changes: 97 additions & 0 deletions src/game/iw2/mp/components/project_velocity.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
#include "pch.h"
#include "project_velocity.h"
#include <cmath>

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<void*>(PV_Config::DummyAddr), reinterpret_cast<void*>(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
31 changes: 31 additions & 0 deletions src/game/iw2/mp/components/project_velocity.h
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions src/game/iw2/mp/main.cpp
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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()
Expand Down
80 changes: 80 additions & 0 deletions src/game/ngl/mp/components/project_velocity.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include "pch.h"
#include "project_velocity.h"
#include <cmath>

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<void*>(PV_Config::DummyAddr), reinterpret_cast<void*>(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
31 changes: 31 additions & 0 deletions src/game/ngl/mp/components/project_velocity.h
Original file line number Diff line number Diff line change
@@ -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
24 changes: 24 additions & 0 deletions src/game/ngl/mp/main.cpp
Original file line number Diff line number Diff line change
@@ -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
17 changes: 17 additions & 0 deletions src/game/ngl/mp/main.h
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions src/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
8 changes: 8 additions & 0 deletions src/plugin_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,14 @@ const GameInfo GAME_INFO[] = {
"Call of Duty: Modern Warfare 3 MP Title Update #24",
&CreatePlugin<iw5::mp::IW5_MP_Plugin>,
},
{
0x415607E1,
0x45B56A5C,// Mon Jan 22 20 : 52 : 28 2007
"codmp_xenonf.xex",
"NGL MP TU3",
"Call of Duty: 3 Title Update #3",
&CreatePlugin<ngl::mp::NGL_MP_Plugin>,
},
};

const GameInfo *FindGameInfo(DWORD title_id, DWORD timestamp)
Expand Down
2 changes: 1 addition & 1 deletion src/version.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Auto-generated version header
#pragma once

#define BUILD_NUMBER 0
#define BUILD_NUMBER 249