From 3d10c578e0b5c23f7eebebad2cc76844be4b40da Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 23 Dec 2015 14:45:53 +0100 Subject: [PATCH] Initial commit. --- .gitignore | 68 +++++++ iw4.sln | 19 ++ iw4/Components/Colors.cpp | 83 +++++++++ iw4/Components/Colors.hpp | 17 ++ iw4/Components/Command.cpp | 63 +++++++ iw4/Components/Command.hpp | 37 ++++ iw4/Components/Console.cpp | 30 ++++ iw4/Components/Console.hpp | 12 ++ iw4/Components/Dvar.cpp | 131 ++++++++++++++ iw4/Components/Dvar.hpp | 36 ++++ iw4/Components/Loader.cpp | 37 ++++ iw4/Components/Loader.hpp | 29 +++ iw4/Components/QuickPatch.cpp | 44 +++++ iw4/Components/QuickPatch.hpp | 9 + iw4/Components/RawFiles.cpp | 24 +++ iw4/Components/RawFiles.hpp | 14 ++ iw4/Components/Window.cpp | 27 +++ iw4/Components/Window.hpp | 12 ++ iw4/Game/Functions.cpp | 41 +++++ iw4/Game/Functions.hpp | 56 ++++++ iw4/Game/Structs.hpp | 123 +++++++++++++ iw4/Main.cpp | 27 +++ iw4/STDInclude.hpp | 22 +++ iw4/Steam/Interfaces/SteamFriends.cpp | 120 +++++++++++++ iw4/Steam/Interfaces/SteamFriends.hpp | 31 ++++ iw4/Steam/Interfaces/SteamGameServer.cpp | 91 ++++++++++ iw4/Steam/Interfaces/SteamGameServer.hpp | 26 +++ .../Interfaces/SteamMasterServerUpdater.cpp | 67 +++++++ .../Interfaces/SteamMasterServerUpdater.hpp | 21 +++ iw4/Steam/Interfaces/SteamMatchmaking.cpp | 170 ++++++++++++++++++ iw4/Steam/Interfaces/SteamMatchmaking.hpp | 41 +++++ iw4/Steam/Interfaces/SteamNetworking.cpp | 104 +++++++++++ iw4/Steam/Interfaces/SteamNetworking.hpp | 27 +++ iw4/Steam/Interfaces/SteamRemoteStorage.cpp | 43 +++++ iw4/Steam/Interfaces/SteamRemoteStorage.hpp | 14 ++ iw4/Steam/Interfaces/SteamUser.cpp | 81 +++++++++ iw4/Steam/Interfaces/SteamUser.hpp | 24 +++ iw4/Steam/Interfaces/SteamUtils.cpp | 96 ++++++++++ iw4/Steam/Interfaces/SteamUtils.hpp | 26 +++ iw4/Steam/Steam.cpp | 100 +++++++++++ iw4/Steam/Steam.hpp | 49 +++++ iw4/Utils/Hooking.cpp | 109 +++++++++++ iw4/Utils/Hooking.hpp | 60 +++++++ iw4/Utils/Utils.cpp | 27 +++ iw4/Utils/Utils.hpp | 5 + iw4/iw4.vcxproj | 107 +++++++++++ iw4/iw4.vcxproj.filters | 164 +++++++++++++++++ iw4/iw4.vcxproj.user | 8 + package.json | 10 ++ 49 files changed, 2582 insertions(+) create mode 100644 .gitignore create mode 100644 iw4.sln create mode 100644 iw4/Components/Colors.cpp create mode 100644 iw4/Components/Colors.hpp create mode 100644 iw4/Components/Command.cpp create mode 100644 iw4/Components/Command.hpp create mode 100644 iw4/Components/Console.cpp create mode 100644 iw4/Components/Console.hpp create mode 100644 iw4/Components/Dvar.cpp create mode 100644 iw4/Components/Dvar.hpp create mode 100644 iw4/Components/Loader.cpp create mode 100644 iw4/Components/Loader.hpp create mode 100644 iw4/Components/QuickPatch.cpp create mode 100644 iw4/Components/QuickPatch.hpp create mode 100644 iw4/Components/RawFiles.cpp create mode 100644 iw4/Components/RawFiles.hpp create mode 100644 iw4/Components/Window.cpp create mode 100644 iw4/Components/Window.hpp create mode 100644 iw4/Game/Functions.cpp create mode 100644 iw4/Game/Functions.hpp create mode 100644 iw4/Game/Structs.hpp create mode 100644 iw4/Main.cpp create mode 100644 iw4/STDInclude.hpp create mode 100644 iw4/Steam/Interfaces/SteamFriends.cpp create mode 100644 iw4/Steam/Interfaces/SteamFriends.hpp create mode 100644 iw4/Steam/Interfaces/SteamGameServer.cpp create mode 100644 iw4/Steam/Interfaces/SteamGameServer.hpp create mode 100644 iw4/Steam/Interfaces/SteamMasterServerUpdater.cpp create mode 100644 iw4/Steam/Interfaces/SteamMasterServerUpdater.hpp create mode 100644 iw4/Steam/Interfaces/SteamMatchmaking.cpp create mode 100644 iw4/Steam/Interfaces/SteamMatchmaking.hpp create mode 100644 iw4/Steam/Interfaces/SteamNetworking.cpp create mode 100644 iw4/Steam/Interfaces/SteamNetworking.hpp create mode 100644 iw4/Steam/Interfaces/SteamRemoteStorage.cpp create mode 100644 iw4/Steam/Interfaces/SteamRemoteStorage.hpp create mode 100644 iw4/Steam/Interfaces/SteamUser.cpp create mode 100644 iw4/Steam/Interfaces/SteamUser.hpp create mode 100644 iw4/Steam/Interfaces/SteamUtils.cpp create mode 100644 iw4/Steam/Interfaces/SteamUtils.hpp create mode 100644 iw4/Steam/Steam.cpp create mode 100644 iw4/Steam/Steam.hpp create mode 100644 iw4/Utils/Hooking.cpp create mode 100644 iw4/Utils/Hooking.hpp create mode 100644 iw4/Utils/Utils.cpp create mode 100644 iw4/Utils/Utils.hpp create mode 100644 iw4/iw4.vcxproj create mode 100644 iw4/iw4.vcxproj.filters create mode 100644 iw4/iw4.vcxproj.user create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..44c814bb --- /dev/null +++ b/.gitignore @@ -0,0 +1,68 @@ +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# ========================= +# Operating System Files +# ========================= + +# OSX +# ========================= + +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +*.obj +*.tlog +*.log +*.lastbuildstate +*.idb +*.exp +*.ilk +*.unsuccessfulbuild +*.sdf +*.opensdf +*.pdb +*.suo + +# Additional stuff +Release +iw4/Release + +# IDA +# ========================= +*.id0 +*.id1 +*.id2 +*.nam +*.til \ No newline at end of file diff --git a/iw4.sln b/iw4.sln new file mode 100644 index 00000000..761e7914 --- /dev/null +++ b/iw4.sln @@ -0,0 +1,19 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iw4", "iw4\iw4.vcxproj", "{38B4FC13-CEBC-4099-8698-3E62943C1EAA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {38B4FC13-CEBC-4099-8698-3E62943C1EAA}.Release|Win32.ActiveCfg = Release|Win32 + {38B4FC13-CEBC-4099-8698-3E62943C1EAA}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/iw4/Components/Colors.cpp b/iw4/Components/Colors.cpp new file mode 100644 index 00000000..ad0aedb7 --- /dev/null +++ b/iw4/Components/Colors.cpp @@ -0,0 +1,83 @@ +#include "..\STDInclude.hpp" + +namespace Components +{ + void Colors::Strip(const char* in, char* out, int max) + { + max--; + int current = 0; + while (*in != 0 && current < max) + { + if (!Q_IsColorString(in)) + { + *out = *in; + out++; + current++; + } + else + { + *in++; + } + *in++; + } + *out = '\0'; + } + + void __declspec(naked) Colors::ClientUserinfoChanged(int length) + { + __asm + { + mov eax, [esp + 4h] // length + sub eax, 1 + push eax + + push ecx // name + push edx // buffer + + call strncpy + + add esp, 0Ch + retn + } + } + + char* Colors::CL_GetClientName(int a1, int a2, char* buffer, size_t _length) + { + __asm + { + push _length + push buffer + push a2 + push a1 + mov eax, 4563D0h + call eax + add esp, 10h + } + + // Remove the colors + char tempBuffer[100] = { 0 }; + Colors::Strip(buffer, tempBuffer, _length); + strncpy(buffer, tempBuffer, _length); + + return buffer; + } + + Colors::Colors() + { + DWORD* color_table = (DWORD*)0x78DC70; + + // Apply NTA's W² colors :3 (slightly modified though^^) + color_table[1] = RGB(255, 49, 49); + color_table[2] = RGB(134, 192, 0); + color_table[3] = RGB(255, 173, 34); + color_table[4] = RGB(0, 135, 193); + color_table[5] = RGB(32, 197, 255); + color_table[6] = RGB(151, 80, 221); + + // Allow colored names ingame + Utils::Hook(0x5D8B40, Colors::ClientUserinfoChanged, HOOK_JUMP).Install()->Quick(); + + // Though, don't apply that to overhead names. + Utils::Hook(0x581932, Colors::CL_GetClientName, HOOK_CALL).Install()->Quick(); + } +} diff --git a/iw4/Components/Colors.hpp b/iw4/Components/Colors.hpp new file mode 100644 index 00000000..5a61cecc --- /dev/null +++ b/iw4/Components/Colors.hpp @@ -0,0 +1,17 @@ +#define Q_IsColorString( p ) ( ( p ) && *( p ) == '^' && *( ( p ) + 1 ) && isdigit( *( ( p ) + 1 ) ) ) // ^[0-9] + + +namespace Components +{ + class Colors : public Component + { + public: + Colors(); + const char* GetName() { return "Colors"; }; + + static void ClientUserinfoChanged(int length); + static char* CL_GetClientName(int a1, int a2, char* buffer, size_t _length); + + static void Strip(const char* in, char* out, int max); + }; +} diff --git a/iw4/Components/Command.cpp b/iw4/Components/Command.cpp new file mode 100644 index 00000000..2beb85b4 --- /dev/null +++ b/iw4/Components/Command.cpp @@ -0,0 +1,63 @@ +#include "..\STDInclude.hpp" + +namespace Components +{ + std::vector Command::Functions; + std::map Command::FunctionMap; + + const char* Command::Params::operator[](size_t index) + { + if (index >= this->Length()) + { + return ""; + } + + return Game::cmd_argv[this->CommandId][index]; + } + + size_t Command::Params::Length() + { + return Game::cmd_argc[this->CommandId]; + } + + Command::~Command() + { + for (auto command : Command::Functions) + { + delete command; + } + + Command::Functions.clear(); + } + + void Command::Add(const char* name, Command::Callback callback) + { + Command::FunctionMap[Utils::StrToLower(name)] = callback; + Game::Cmd_AddCommand(name, Command::MainCallback, Command::Allocate(), 0); + } + + Game::cmd_function_t* Command::Allocate() + { + Game::cmd_function_t* cmd = new Game::cmd_function_t; + Command::Functions.push_back(cmd); + + return cmd; + } + + void Command::MainCallback() + { + Command::Params params(*Game::cmd_id); + + std::string command = Utils::StrToLower(params[0]); + + if (Command::FunctionMap.find(command) != Command::FunctionMap.end()) + { + Command::FunctionMap[command](params); + } + } + + Command::Command() + { + // TODO: Add commands here? + } +} diff --git a/iw4/Components/Command.hpp b/iw4/Components/Command.hpp new file mode 100644 index 00000000..3110dc12 --- /dev/null +++ b/iw4/Components/Command.hpp @@ -0,0 +1,37 @@ +#define Q_IsColorString( p ) ( ( p ) && *( p ) == '^' && *( ( p ) + 1 ) && isdigit( *( ( p ) + 1 ) ) ) // ^[0-9] + + +namespace Components +{ + class Command : public Component + { + public: + class Params + { + public: + Params(DWORD id) : CommandId(id) {}; + Params(const Params &obj) { this->CommandId = obj.CommandId; }; + + const char* operator[](size_t index); + size_t Length(); + + private: + DWORD CommandId; + }; + + typedef void(*Callback)(Command::Params params); + + Command(); + ~Command(); + const char* GetName() { return "Command"; }; + + static void Add(const char* name, Callback callback); + static int ArgCount(); + + private: + static Game::cmd_function_t* Allocate(); + static std::vector Functions; + static std::map FunctionMap; + static void MainCallback(); + }; +} diff --git a/iw4/Components/Console.cpp b/iw4/Components/Console.cpp new file mode 100644 index 00000000..a7977869 --- /dev/null +++ b/iw4/Components/Console.cpp @@ -0,0 +1,30 @@ +#include "..\STDInclude.hpp" + +namespace Components +{ + void Console::ToggleConsole() + { + // possibly cls.keyCatchers? + DWORD catcher = 0xB2C538; + Utils::Hook::Set(catcher, Utils::Hook::Get(catcher) ^ 1); + + // g_consoleField + Game::Field_Clear((void*)0xA1B6B0); + + // show console output? + Utils::Hook::Set(0xA15F38, 0); + } + + Console::Console() + { + // External console + Utils::Hook::Nop(0x60BB58, 11); + + // Console '%s: %s> ' string + Utils::Hook::Set(0x5A44B4, "IW4x > "); + + // Internal console + Utils::Hook(0x4F690C, Console::ToggleConsole, HOOK_CALL).Install()->Quick(); + Utils::Hook(0x4F65A5, Console::ToggleConsole, HOOK_JUMP).Install()->Quick(); + } +} diff --git a/iw4/Components/Console.hpp b/iw4/Components/Console.hpp new file mode 100644 index 00000000..5c53eda0 --- /dev/null +++ b/iw4/Components/Console.hpp @@ -0,0 +1,12 @@ +namespace Components +{ + class Console : public Component + { + public: + Console(); + const char* GetName() { return "Console"; }; + + private: + static void ToggleConsole(); + }; +} diff --git a/iw4/Components/Dvar.cpp b/iw4/Components/Dvar.cpp new file mode 100644 index 00000000..8aadf80d --- /dev/null +++ b/iw4/Components/Dvar.cpp @@ -0,0 +1,131 @@ +#include "..\STDInclude.hpp" + +namespace Components +{ + Dvar::Var::Var(std::string dvarName) : Var() + { + this->dvar = Game::Dvar_FindVar(dvarName.data()); + + if (!this->dvar) + { + // Register the dvar? + } + } + + template <> char* Dvar::Var::Get() + { + if (this->dvar && this->dvar->type == Game::dvar_type::DVAR_TYPE_STRING && this->dvar->current.string) + { + return this->dvar->current.string; + } + + return ""; + } + + template <> const char* Dvar::Var::Get() + { + return this->Get(); + } + + template <> int Dvar::Var::Get() + { + if (this->dvar && this->dvar->type == Game::dvar_type::DVAR_TYPE_INT) + { + return this->dvar->current.integer; + } + + return 0; + } + + template <> float Dvar::Var::Get() + { + if (this->dvar && this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT) + { + return this->dvar->current.value; + } + + return 0; + } + + template <> float* Dvar::Var::Get() + { + static float val[4] = { 0 }; + + if (this->dvar && (this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT_2 || this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT_3 || this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT_4)) + { + return this->dvar->current.vec4; + } + + return val; + } + + template <> bool Dvar::Var::Get() + { + if (this->dvar && this->dvar->type == Game::dvar_type::DVAR_TYPE_BOOL) + { + return this->dvar->current.boolean; + } + + return false; + } + + void Dvar::Var::Set(char* string) + { + this->Set(reinterpret_cast(string)); + } + + void Dvar::Var::Set(const char* string) + { + if (this->dvar && this->dvar->name) + { + Game::Dvar_SetCommand(this->dvar->name, string); + } + } + + void Dvar::Var::Set(std::string string) + { + this->Set(string.data()); + } + + void Dvar::Var::Set(int integer) + { + if (this->dvar && this->dvar->name) + { + Game::Dvar_SetCommand(this->dvar->name, Utils::VA("%i", integer)); + } + } + + void Dvar::Var::Set(float value) + { + if (this->dvar && this->dvar->name) + { + Game::Dvar_SetCommand(this->dvar->name, Utils::VA("%f", value)); + } + } + + template<> static Dvar::Var Dvar::Var::Register(const char* name, bool value, Game::dvar_flag flag, const char* description) + { + return Game::Dvar_RegisterBool(name, value, flag, description); + } + + template<> static Dvar::Var Dvar::Var::Register(const char* name, const char* value, Game::dvar_flag flag, const char* description) + { + return Game::Dvar_RegisterString(name, value, flag, description); + } + + Dvar::Dvar() + { + // set flags of cg_drawFPS to archive + *(BYTE*)0x4F8F69 |= Game::dvar_flag::DVAR_FLAG_SAVED; + + // un-cheat cg_fov and add archive flags + *(BYTE*)0x4F8E35 ^= Game::dvar_flag::DVAR_FLAG_CHEAT | Game::dvar_flag::DVAR_FLAG_SAVED; + + // set cg_fov max to 90.0 + static float cgFov90 = 90.0f; + *(DWORD*)0x4F8E28 = (DWORD)&cgFov90; + + Dvar::Var::Register("zob", true, Game::dvar_flag::DVAR_FLAG_NONE, "test dvar"); + //Dvar::Var::Register("zob2", "test", Game::dvar_flag::DVAR_FLAG_NONE, "test dvar3"); + } +} diff --git a/iw4/Components/Dvar.hpp b/iw4/Components/Dvar.hpp new file mode 100644 index 00000000..0c315305 --- /dev/null +++ b/iw4/Components/Dvar.hpp @@ -0,0 +1,36 @@ +namespace Components +{ + class Dvar : public Component + { + public: + class Var + { + public: + Var() : dvar(0) {}; + Var(const Var &obj) { this->dvar = obj.dvar; }; + Var(Game::dvar_t* _dvar) : dvar(_dvar) {}; + Var(std::string dvarName); + + template T Get(); + + void Set(char* string); + void Set(const char* string); + void Set(std::string string); + + void Set(int integer); + void Set(float value); + + // Only strings and bools use this type of declaration + template static Var Register(const char* name, T value, Game::dvar_flag flag, const char* description); + + private: + Game::dvar_t* dvar; + }; + + Dvar(); + const char* GetName() { return "Dvar"; }; + + private: + + }; +} diff --git a/iw4/Components/Loader.cpp b/iw4/Components/Loader.cpp new file mode 100644 index 00000000..75b1a570 --- /dev/null +++ b/iw4/Components/Loader.cpp @@ -0,0 +1,37 @@ +#include "..\STDInclude.hpp" + +namespace Components +{ + std::vector Loader::Components; + + void Loader::Initialize() + { + Loader::Register(new Dvar()); + Loader::Register(new Colors()); + Loader::Register(new Window()); + Loader::Register(new Command()); + Loader::Register(new Console()); + Loader::Register(new RawFiles()); + Loader::Register(new QuickPatch()); + } + + void Loader::Uninitialize() + { + for (auto component : Loader::Components) + { + OutputDebugStringA(Utils::VA("Unregistering component: %s", component->GetName())); + delete component; + } + + Loader::Components.clear(); + } + + void Loader::Register(Component* component) + { + if (component) + { + OutputDebugStringA(Utils::VA("Component registered: %s", component->GetName())); + Loader::Components.push_back(component); + } + } +} diff --git a/iw4/Components/Loader.hpp b/iw4/Components/Loader.hpp new file mode 100644 index 00000000..7e40b4df --- /dev/null +++ b/iw4/Components/Loader.hpp @@ -0,0 +1,29 @@ +namespace Components +{ + class Component + { + public: + Component() {}; + virtual ~Component() {}; + virtual const char* GetName() { return "Unknown"; }; + }; + + class Loader + { + public: + static void Initialize(); + static void Uninitialize(); + static void Register(Component* component); + + private: + static std::vector Components; + }; +} + +#include "Dvar.hpp" +#include "Colors.hpp" +#include "Window.hpp" +#include "Command.hpp" +#include "Console.hpp" +#include "RawFiles.hpp" +#include "QuickPatch.hpp" diff --git a/iw4/Components/QuickPatch.cpp b/iw4/Components/QuickPatch.cpp new file mode 100644 index 00000000..9f384c36 --- /dev/null +++ b/iw4/Components/QuickPatch.cpp @@ -0,0 +1,44 @@ +#include "..\STDInclude.hpp" + +namespace Components +{ + QuickPatch::QuickPatch() + { + // remove system pre-init stuff (improper quit, disk full) + Utils::Hook::Set(0x411350, 0xC3); + + // remove STEAMSTART checking for DRM IPC + Utils::Hook::Nop(0x451145, 5); + Utils::Hook::Set(0x45114C, 0xEB); + + // disable playlist download function + Utils::Hook::Set(0x4D4790, 0xC3); + + // disable playlist.ff loading function + Utils::Hook::Set(0x4D6E60, 0xC3); + + // playlist dvar 'validity check' + Utils::Hook::Set(0x4B1170, 0xC3); + + //Got playlists is true + Utils::Hook::Set(0x1AD3680, true); + + // LSP disabled + Utils::Hook::Set(0x435950, 0xC3); // LSP HELLO + Utils::Hook::Set(0x49C220, 0xC3); // We wanted to send a logging packet, but we haven't connected to LSP! + Utils::Hook::Set(0x4BD900, 0xC3); // main LSP response func + Utils::Hook::Set(0x682170, 0xC3); // Telling LSP that we're playing a private match + + // Don't delete config files if corrupted + Utils::Hook::Set(0x47DCB3, 0xEB); + + // hopefully allow alt-tab during game, used at least in alt-enter handling + Utils::Hook::Set(0x45ACE0, 0xC301B0); + + // fs_basegame + Utils::Hook::Set(0x6431D1, "data"); + + // Why? + Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_WEAPON, 2400); + } +} diff --git a/iw4/Components/QuickPatch.hpp b/iw4/Components/QuickPatch.hpp new file mode 100644 index 00000000..11984c3f --- /dev/null +++ b/iw4/Components/QuickPatch.hpp @@ -0,0 +1,9 @@ +namespace Components +{ + class QuickPatch : public Component + { + public: + QuickPatch(); + const char* GetName() { return "QuickPatch"; }; + }; +} diff --git a/iw4/Components/RawFiles.cpp b/iw4/Components/RawFiles.cpp new file mode 100644 index 00000000..4c816e29 --- /dev/null +++ b/iw4/Components/RawFiles.cpp @@ -0,0 +1,24 @@ +#include "..\STDInclude.hpp" + +namespace Components +{ + void* RawFiles::LoadModdableRawfileFunc(const char* filename) + { + return Game::LoadModdableRawfile(0, filename); + } + + RawFiles::RawFiles() + { + Utils::Hook(0x632155, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick(); + Utils::Hook(0x5FA46C, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick(); + Utils::Hook(0x5FA4D6, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick(); + Utils::Hook(0x6321EF, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick(); + Utils::Hook(0x630A88, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick(); + Utils::Hook(0x59A6F8, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick(); + Utils::Hook(0x57F1E6, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick(); + Utils::Hook(0x57ED36, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick(); + + // remove fs_game check for moddable rawfiles - allows non-fs_game to modify rawfiles + Utils::Hook::Nop(0x61AB76, 2); + } +} diff --git a/iw4/Components/RawFiles.hpp b/iw4/Components/RawFiles.hpp new file mode 100644 index 00000000..73b162a3 --- /dev/null +++ b/iw4/Components/RawFiles.hpp @@ -0,0 +1,14 @@ +#define Q_IsColorString( p ) ( ( p ) && *( p ) == '^' && *( ( p ) + 1 ) && isdigit( *( ( p ) + 1 ) ) ) // ^[0-9] + + +namespace Components +{ + class RawFiles : public Component + { + public: + RawFiles(); + const char* GetName() { return "RawFiles"; }; + + static void* RawFiles::LoadModdableRawfileFunc(const char* filename); + }; +} diff --git a/iw4/Components/Window.cpp b/iw4/Components/Window.cpp new file mode 100644 index 00000000..8c93be99 --- /dev/null +++ b/iw4/Components/Window.cpp @@ -0,0 +1,27 @@ +#include "..\STDInclude.hpp" + +namespace Components +{ + Dvar::Var Window::NoBorder; + + void __declspec(naked) Window::StyleHookStub() + { + if (Window::NoBorder.Get()) + { + __asm mov ebp, WS_VISIBLE | WS_POPUP + } + else + { + __asm mov ebp, WS_VISIBLE | WS_SYSMENU | WS_CAPTION + } + + __asm retn + } + + Window::Window() + { + // Borderless window + Window::NoBorder = Dvar::Var::Register("r_noborder", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Do not use a border in windowed mode"); + Utils::Hook(0x507643, Window::StyleHookStub, HOOK_CALL).Install()->Quick(); + } +} diff --git a/iw4/Components/Window.hpp b/iw4/Components/Window.hpp new file mode 100644 index 00000000..0ec8ec53 --- /dev/null +++ b/iw4/Components/Window.hpp @@ -0,0 +1,12 @@ +namespace Components +{ + class Window : public Component + { + public: + Window(); + const char* GetName() { return "Window"; }; + + static Dvar::Var NoBorder; + static void Window::StyleHookStub(); + }; +} diff --git a/iw4/Game/Functions.cpp b/iw4/Game/Functions.cpp new file mode 100644 index 00000000..26ef3831 --- /dev/null +++ b/iw4/Game/Functions.cpp @@ -0,0 +1,41 @@ +#include "..\STDInclude.hpp" + +namespace Game +{ + Cmd_AddCommand_t Cmd_AddCommand = (Cmd_AddCommand_t)0x470090; + + DB_GetXAssetSizeHandler_t* DB_GetXAssetSizeHandlers = (DB_GetXAssetSizeHandler_t*)0x799488; + + Dvar_RegisterBool_t Dvar_RegisterBool = (Dvar_RegisterBool_t)0x4CE1A0; + Dvar_RegisterFloat_t Dvar_RegisterFloat = (Dvar_RegisterFloat_t)0x648440; + Dvar_RegisterFloat2_t Dvar_RegisterFloat2 = (Dvar_RegisterFloat2_t)0x4F6070; + Dvar_RegisterFloat3_t Dvar_RegisterFloat3 = (Dvar_RegisterFloat3_t)0x4EF8E0; + Dvar_RegisterFloat4_t Dvar_RegisterFloat4 = (Dvar_RegisterFloat4_t)0x4F28E0; + Dvar_RegisterInt_t Dvar_RegisterInt = (Dvar_RegisterInt_t)0x479830; + Dvar_RegisterEnum_t Dvar_RegisterEnum = (Dvar_RegisterEnum_t)0x412E40; + Dvar_RegisterString_t Dvar_RegisterString = (Dvar_RegisterString_t)0x4FC7E0; + Dvar_RegisterColor_t Dvar_RegisterColor = (Dvar_RegisterColor_t)0x471500; + + Dvar_FindVar_t Dvar_FindVar = (Dvar_FindVar_t)0x4D5390; + Dvar_SetCommand_t Dvar_SetCommand = (Dvar_SetCommand_t)0x4EE430; + + Field_Clear_t Field_Clear = (Field_Clear_t)0x437EB0; + + LoadModdableRawfile_t LoadModdableRawfile = (LoadModdableRawfile_t)0x61ABC0; + + void** DB_XAssetPool = (void**)0x7998A8; + unsigned int* g_poolSize = (unsigned int*)0x7995E8; + + DWORD* cmd_id = (DWORD*)0x1AAC5D0; + DWORD* cmd_argc = (DWORD*)0x1AAC614; + char*** cmd_argv = (char***)0x1AAC634; + + void* ReallocateAssetPool(XAssetType type, unsigned int newSize) + { + int elSize = DB_GetXAssetSizeHandlers[type](); + void* poolEntry = new char[newSize * elSize]; + DB_XAssetPool[type] = poolEntry; + g_poolSize[type] = newSize; + return poolEntry; + } +} \ No newline at end of file diff --git a/iw4/Game/Functions.hpp b/iw4/Game/Functions.hpp new file mode 100644 index 00000000..0945c039 --- /dev/null +++ b/iw4/Game/Functions.hpp @@ -0,0 +1,56 @@ +namespace Game +{ + typedef void(__cdecl * Cmd_AddCommand_t)(const char* name, void(*callback), cmd_function_t* data, char); + extern Cmd_AddCommand_t Cmd_AddCommand; + + typedef int(__cdecl * DB_GetXAssetSizeHandler_t)(); + extern DB_GetXAssetSizeHandler_t* DB_GetXAssetSizeHandlers; + + typedef dvar_t* (__cdecl * Dvar_RegisterBool_t)(const char* name, bool default, int flags, const char* description); + extern Dvar_RegisterBool_t Dvar_RegisterBool; + + typedef dvar_t* (__cdecl * Dvar_RegisterFloat_t)(const char* name, float default, float min, float max, int flags, const char* description); + extern Dvar_RegisterFloat_t Dvar_RegisterFloat; + + typedef dvar_t* (__cdecl * Dvar_RegisterFloat2_t)(const char* name, float defx, float defy, float min, float max, int flags, const char* description); + extern Dvar_RegisterFloat2_t Dvar_RegisterFloat2; + + typedef dvar_t* (__cdecl * Dvar_RegisterFloat3_t)(const char* name, float defx, float defy, float defz, float min, float max, int flags, const char* description); + extern Dvar_RegisterFloat3_t Dvar_RegisterFloat3; + + typedef dvar_t* (__cdecl * Dvar_RegisterFloat4_t)(const char* name, float defx, float defy, float defz, float defw, float min, float max, int flags, const char* description); + extern Dvar_RegisterFloat4_t Dvar_RegisterFloat4; + + typedef dvar_t* (__cdecl * Dvar_RegisterInt_t)(const char* name, int default, int min, int max, int flags, const char* description); + extern Dvar_RegisterInt_t Dvar_RegisterInt; + + typedef dvar_t* (__cdecl * Dvar_RegisterEnum_t)(const char* name, char** enumValues, int default, int flags, const char* description); + extern Dvar_RegisterEnum_t Dvar_RegisterEnum; + + typedef dvar_t* (__cdecl * Dvar_RegisterString_t)(const char* name, const char* default, int, const char*); + extern Dvar_RegisterString_t Dvar_RegisterString; + + typedef dvar_t* (__cdecl * Dvar_RegisterColor_t)(const char* name, float r, float g, float b, float a, int flags, const char* description); + extern Dvar_RegisterColor_t Dvar_RegisterColor; + + typedef dvar_t* (__cdecl * Dvar_FindVar_t)(const char *dvarName); + extern Dvar_FindVar_t Dvar_FindVar; + + typedef dvar_t* (__cdecl * Dvar_SetCommand_t)(const char* name, const char* value); + extern Dvar_SetCommand_t Dvar_SetCommand; + + typedef void(__cdecl * Field_Clear_t)(void* field); + extern Field_Clear_t Field_Clear; + + typedef void* (__cdecl * LoadModdableRawfile_t)(int a1, const char* filename); + extern LoadModdableRawfile_t LoadModdableRawfile; + + extern void** DB_XAssetPool; + extern unsigned int* g_poolSize; + + extern DWORD* cmd_id; + extern DWORD* cmd_argc; + extern char*** cmd_argv; + + void* ReallocateAssetPool(XAssetType type, unsigned int newSize); +} diff --git a/iw4/Game/Structs.hpp b/iw4/Game/Structs.hpp new file mode 100644 index 00000000..0d246868 --- /dev/null +++ b/iw4/Game/Structs.hpp @@ -0,0 +1,123 @@ +namespace Game +{ + typedef enum + { + ASSET_TYPE_PHYSPRESET = 0, + ASSET_TYPE_PHYS_COLLMAP = 1, + ASSET_TYPE_XANIM = 2, + ASSET_TYPE_XMODELSURFS = 3, + ASSET_TYPE_XMODEL = 4, + ASSET_TYPE_MATERIAL = 5, + ASSET_TYPE_PIXELSHADER = 6, + ASSET_TYPE_VERTEXSHADER = 7, + ASSET_TYPE_VERTEXDECL = 8, + ASSET_TYPE_TECHSET = 9, + ASSET_TYPE_IMAGE = 10, + ASSET_TYPE_SOUND = 11, + ASSET_TYPE_SNDCURVE = 12, + ASSET_TYPE_LOADED_SOUND = 13, + ASSET_TYPE_COL_MAP_SP = 14, + ASSET_TYPE_COL_MAP_MP = 15, + ASSET_TYPE_COM_MAP = 16, + ASSET_TYPE_GAME_MAP_SP = 17, + ASSET_TYPE_GAME_MAP_MP = 18, + ASSET_TYPE_MAP_ENTS = 19, + ASSET_TYPE_FX_MAP = 20, + ASSET_TYPE_GFX_MAP = 21, + ASSET_TYPE_LIGHTDEF = 22, + ASSET_TYPE_UI_MAP = 23, + ASSET_TYPE_FONT = 24, + ASSET_TYPE_MENUFILE = 25, + ASSET_TYPE_MENU = 26, + ASSET_TYPE_LOCALIZE = 27, + ASSET_TYPE_WEAPON = 28, + ASSET_TYPE_SNDDRIVERGLOBALS = 29, + ASSET_TYPE_FX = 30, + ASSET_TYPE_IMPACTFX = 31, + ASSET_TYPE_AITYPE = 32, + ASSET_TYPE_MPTYPE = 33, + ASSET_TYPE_CHARACTER = 34, + ASSET_TYPE_XMODELALIAS = 35, + ASSET_TYPE_RAWFILE = 36, + ASSET_TYPE_STRINGTABLE = 37, + ASSET_TYPE_LEADERBOARDDEF = 38, + ASSET_TYPE_STRUCTUREDDATADEF = 39, + ASSET_TYPE_TRACER = 40, + ASSET_TYPE_VEHICLE = 41, + ASSET_TYPE_ADDON_MAP_ENTS = 42, + ASSET_TYPE_MAX = 43 + } XAssetType; + + typedef enum + { + DVAR_FLAG_NONE = 0x0, //no flags + DVAR_FLAG_SAVED = 0x1, //saves in config_mp.cfg for clients + DVAR_FLAG_LATCHED = 0x2, //no changing apart from initial value (although it might apply on a map reload, I think) + DVAR_FLAG_CHEAT = 0x4, //cheat + DVAR_FLAG_REPLICATED = 0x8, //on change, this is sent to all clients (if you are host) + DVAR_FLAG_UNKNOWN10 = 0x10, //unknown + DVAR_FLAG_UNKNOWN20 = 0x20, //unknown + DVAR_FLAG_UNKNOWN40 = 0x40, //unknown + DVAR_FLAG_UNKNOWN80 = 0x80, //unknown + DVAR_FLAG_USERCREATED = 0x100, //a 'set' type command created it + DVAR_FLAG_USERINFO = 0x200, //userinfo? + DVAR_FLAG_SERVERINFO = 0x400, //in the getstatus oob + DVAR_FLAG_WRITEPROTECTED = 0x800, //write protected + DVAR_FLAG_UNKNOWN1000 = 0x1000, //unknown + DVAR_FLAG_READONLY = 0x2000, //read only (same as 0x800?) + DVAR_FLAG_UNKNOWN4000 = 0x4000, //unknown + DVAR_FLAG_UNKNOWN8000 = 0x8000, //unknown + DVAR_FLAG_UNKNOWN10000 = 0x10000, //unknown + DVAR_FLAG_DEDISAVED = 0x1000000, //unknown + DVAR_FLAG_NONEXISTENT = 0xFFFFFFFF //no such dvar + } dvar_flag; + + typedef enum + { + DVAR_TYPE_BOOL = 0, + DVAR_TYPE_FLOAT = 1, + DVAR_TYPE_FLOAT_2 = 2, + DVAR_TYPE_FLOAT_3 = 3, + DVAR_TYPE_FLOAT_4 = 4, + DVAR_TYPE_INT = 5, + DVAR_TYPE_ENUM = 6, + DVAR_TYPE_STRING = 7, + DVAR_TYPE_COLOR = 8, + //DVAR_TYPE_INT64 = 9 only in Tx + } dvar_type; + // 67/72 bytes figured out + union dvar_value_t { + char* string; + int integer; + float value; + bool boolean; + float vec2[2]; + float vec3[3]; + float vec4[4]; + BYTE color[4]; //to get float: multiply by 0.003921568859368563 - BaberZz + //__int64 integer64; only in Tx + }; + union dvar_maxmin_t { + int i; + float f; + }; + typedef struct dvar_t + { + //startbyte:endbyte + const char* name; //0:3 + const char* description; //4:7 + unsigned int flags; //8:11 + char type; //12:12 + char pad2[3]; //13:15 + dvar_value_t current; //16:31 + dvar_value_t latched; //32:47 + dvar_value_t default; //48:64 + dvar_maxmin_t min; //65:67 + dvar_maxmin_t max; //68:72 woooo + } dvar_t; + + typedef struct cmd_function_s + { + char pad[24]; + } cmd_function_t; +} diff --git a/iw4/Main.cpp b/iw4/Main.cpp new file mode 100644 index 00000000..d183162c --- /dev/null +++ b/iw4/Main.cpp @@ -0,0 +1,27 @@ +#include "STDInclude.hpp" + +Utils::Hook EntryPointHook; + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + if (ul_reason_for_call == DLL_PROCESS_ATTACH) + { + FreeConsole(); + + DWORD oldProtect; + VirtualProtect(GetModuleHandle(NULL), 0x6C73000, PAGE_EXECUTE_READWRITE, &oldProtect); + + EntryPointHook.Initialize(0x6BAC0F, static_cast([] () + { + EntryPointHook.Uninstall(); + Components::Loader::Initialize(); + __asm jmp EntryPointHook.Place + }))->Install(); + } + else if (ul_reason_for_call == DLL_PROCESS_DETACH) + { + Components::Loader::Uninitialize(); + } + + return TRUE; +} diff --git a/iw4/STDInclude.hpp b/iw4/STDInclude.hpp new file mode 100644 index 00000000..3d435f0a --- /dev/null +++ b/iw4/STDInclude.hpp @@ -0,0 +1,22 @@ +#pragma once +#define _CRT_SECURE_NO_WARNINGS +#define WIN32_LEAN_AND_MEAN + +#include +#include + +#include +#include +#include +#include +#include + +#include "Game\Structs.hpp" +#include "Game\Functions.hpp" + +#include "Utils\Utils.hpp" +#include "Utils\Hooking.hpp" + +#include "Steam\Steam.hpp" + +#include "Components\Loader.hpp" diff --git a/iw4/Steam/Interfaces/SteamFriends.cpp b/iw4/Steam/Interfaces/SteamFriends.cpp new file mode 100644 index 00000000..a7da14d7 --- /dev/null +++ b/iw4/Steam/Interfaces/SteamFriends.cpp @@ -0,0 +1,120 @@ +#include "..\..\STDInclude.hpp" + +using namespace Components; + +namespace Steam +{ + const char *Friends::GetPersonaName() + { + return Dvar::Var("name").Get(); + } + + void Friends::SetPersonaName(const char *pchPersonaName) + { + Dvar::Var("name").Set(pchPersonaName); + } + + int Friends::GetPersonaState() + { + return 1; + } + + int Friends::GetFriendCount(int eFriendFlags) + { + return 0; + } + + SteamID Friends::GetFriendByIndex(int iFriend, int iFriendFlags) + { + return SteamID(); + } + + int Friends::GetFriendRelationship(SteamID steamIDFriend) + { + return 0; + } + + int Friends::GetFriendPersonaState(SteamID steamIDFriend) + { + return 0; + } + + const char *Friends::GetFriendPersonaName(SteamID steamIDFriend) + { + return ""; + } + + int Friends::GetFriendAvatar(SteamID steamIDFriend, int eAvatarSize) + { + return 0; + } + + bool Friends::GetFriendGamePlayed(SteamID steamIDFriend, void *pFriendGameInfo) + { + return false; + } + + const char *Friends::GetFriendPersonaNameHistory(SteamID steamIDFriend, int iPersonaName) + { + return ""; + } + + bool Friends::HasFriend(SteamID steamIDFriend, int eFriendFlags) + { + return false; + } + + int Friends::GetClanCount() + { + return 0; + } + + SteamID Friends::GetClanByIndex(int iClan) + { + return SteamID(); + } + + const char *Friends::GetClanName(SteamID steamIDClan) + { + return "3arc"; + } + + int Friends::GetFriendCountFromSource(SteamID steamIDSource) + { + return 0; + } + + SteamID Friends::GetFriendFromSourceByIndex(SteamID steamIDSource, int iFriend) + { + return SteamID(); + } + + bool Friends::IsUserInSource(SteamID steamIDUser, SteamID steamIDSource) + { + return false; + } + + void Friends::SetInGameVoiceSpeaking(SteamID steamIDUser, bool bSpeaking) + { + } + + void Friends::ActivateGameOverlay(const char *pchDialog) + { + } + + void Friends::ActivateGameOverlayToUser(const char *pchDialog, SteamID steamID) + { + } + + void Friends::ActivateGameOverlayToWebPage(const char *pchURL) + { + } + + void Friends::ActivateGameOverlayToStore(unsigned int nAppID) + { + } + + void Friends::SetPlayedWith(SteamID steamIDUserPlayedWith) + { + } +} diff --git a/iw4/Steam/Interfaces/SteamFriends.hpp b/iw4/Steam/Interfaces/SteamFriends.hpp new file mode 100644 index 00000000..2727e2df --- /dev/null +++ b/iw4/Steam/Interfaces/SteamFriends.hpp @@ -0,0 +1,31 @@ +namespace Steam +{ + class Friends + { + public: + virtual const char *GetPersonaName(); + virtual void SetPersonaName(const char *pchPersonaName); + virtual int GetPersonaState(); + virtual int GetFriendCount(int eFriendFlags); + virtual SteamID GetFriendByIndex(int iFriend, int iFriendFlags); + virtual int GetFriendRelationship(SteamID steamIDFriend); + virtual int GetFriendPersonaState(SteamID steamIDFriend); + virtual const char *GetFriendPersonaName(SteamID steamIDFriend); + virtual int GetFriendAvatar(SteamID steamIDFriend, int eAvatarSize); + virtual bool GetFriendGamePlayed(SteamID steamIDFriend, void *pFriendGameInfo); + virtual const char *GetFriendPersonaNameHistory(SteamID steamIDFriend, int iPersonaName); + virtual bool HasFriend(SteamID steamIDFriend, int eFriendFlags); + virtual int GetClanCount(); + virtual SteamID GetClanByIndex(int iClan); + virtual const char *GetClanName(SteamID steamIDClan); + virtual int GetFriendCountFromSource(SteamID steamIDSource); + virtual SteamID GetFriendFromSourceByIndex(SteamID steamIDSource, int iFriend); + virtual bool IsUserInSource(SteamID steamIDUser, SteamID steamIDSource); + virtual void SetInGameVoiceSpeaking(SteamID steamIDUser, bool bSpeaking); + virtual void ActivateGameOverlay(const char *pchDialog); + virtual void ActivateGameOverlayToUser(const char *pchDialog, SteamID steamID); + virtual void ActivateGameOverlayToWebPage(const char *pchURL); + virtual void ActivateGameOverlayToStore(unsigned int nAppID); + virtual void SetPlayedWith(SteamID steamIDUserPlayedWith); + }; +} diff --git a/iw4/Steam/Interfaces/SteamGameServer.cpp b/iw4/Steam/Interfaces/SteamGameServer.cpp new file mode 100644 index 00000000..0d302013 --- /dev/null +++ b/iw4/Steam/Interfaces/SteamGameServer.cpp @@ -0,0 +1,91 @@ +#include "..\..\STDInclude.hpp" + +namespace Steam +{ + void GameServer::LogOn() + { + } + + void GameServer::LogOff() + { + } + + bool GameServer::LoggedOn() + { + return true; + } + + bool GameServer::Secure() + { + return false; + } + + SteamID GameServer::GetSteamID() + { + return SteamID(); + } + + bool GameServer::SendUserConnectAndAuthenticate(unsigned int unIPClient, const void *pvAuthBlob, unsigned int cubAuthBlobSize, SteamID *pSteamIDUser) + { + return true; + } + + SteamID GameServer::CreateUnauthenticatedUserConnection() + { + return SteamID(); + } + + void GameServer::SendUserDisconnect(SteamID steamIDUser) + { + } + + bool GameServer::UpdateUserData(SteamID steamIDUser, const char *pchPlayerName, unsigned int uScore) + { + return true; + } + + bool GameServer::SetServerType(unsigned int unServerFlags, unsigned int unGameIP, unsigned short unGamePort, unsigned short unSpectatorPort, unsigned short usQueryPort, const char *pchGameDir, const char *pchVersion, bool bLANMode) + { + return true; + } + + void GameServer::UpdateServerStatus(int cPlayers, int cPlayersMax, int cBotPlayers, const char *pchServerName, const char *pSpectatorServerName, const char *pchMapName) + { + } + + void GameServer::UpdateSpectatorPort(unsigned short unSpectatorPort) + { + } + + void GameServer::SetGameType(const char *pchGameType) + { + } + + bool GameServer::GetUserAchievementStatus(SteamID steamID, const char *pchAchievementName) + { + return false; + } + + void GameServer::GetGameplayStats() + { + } + + bool GameServer::RequestUserGroupStatus(SteamID steamIDUser, SteamID steamIDGroup) + { + return false; + } + + unsigned int GameServer::GetPublicIP() + { + return 0; + } + + void GameServer::SetGameData(const char *pchGameData) + { + } + + int GameServer::UserHasLicenseForApp(SteamID steamID, unsigned int appID) + { + return 0; + } +} diff --git a/iw4/Steam/Interfaces/SteamGameServer.hpp b/iw4/Steam/Interfaces/SteamGameServer.hpp new file mode 100644 index 00000000..2a899701 --- /dev/null +++ b/iw4/Steam/Interfaces/SteamGameServer.hpp @@ -0,0 +1,26 @@ +namespace Steam +{ + class GameServer + { + public: + virtual void LogOn(); + virtual void LogOff(); + virtual bool LoggedOn(); + virtual bool Secure(); + virtual SteamID GetSteamID(); + virtual bool SendUserConnectAndAuthenticate(unsigned int unIPClient, const void *pvAuthBlob, unsigned int cubAuthBlobSize, SteamID *pSteamIDUser); + virtual SteamID CreateUnauthenticatedUserConnection(); + virtual void SendUserDisconnect(SteamID steamIDUser); + virtual bool UpdateUserData(SteamID steamIDUser, const char *pchPlayerName, unsigned int uScore); + virtual bool SetServerType(unsigned int unServerFlags, unsigned int unGameIP, unsigned short unGamePort, unsigned short unSpectatorPort, unsigned short usQueryPort, const char *pchGameDir, const char *pchVersion, bool bLANMode); + virtual void UpdateServerStatus(int cPlayers, int cPlayersMax, int cBotPlayers, const char *pchServerName, const char *pSpectatorServerName, const char *pchMapName); + virtual void UpdateSpectatorPort(unsigned short unSpectatorPort); + virtual void SetGameType(const char *pchGameType); + virtual bool GetUserAchievementStatus(SteamID steamID, const char *pchAchievementName); + virtual void GetGameplayStats(); + virtual bool RequestUserGroupStatus(SteamID steamIDUser, SteamID steamIDGroup); + virtual unsigned int GetPublicIP(); + virtual void SetGameData(const char *pchGameData); + virtual int UserHasLicenseForApp(SteamID steamID, unsigned int appID); + }; +} diff --git a/iw4/Steam/Interfaces/SteamMasterServerUpdater.cpp b/iw4/Steam/Interfaces/SteamMasterServerUpdater.cpp new file mode 100644 index 00000000..f7411f59 --- /dev/null +++ b/iw4/Steam/Interfaces/SteamMasterServerUpdater.cpp @@ -0,0 +1,67 @@ +#include "..\..\STDInclude.hpp" + +namespace Steam +{ + void MasterServerUpdater::SetActive(bool bActive) + { + } + + void MasterServerUpdater::SetHeartbeatInterval(int iHeartbeatInterval) + { + } + + bool MasterServerUpdater::HandleIncomingPacket(const void *pData, int cbData, unsigned int srcIP, unsigned short srcPort) + { + return true; + } + + int MasterServerUpdater::GetNextOutgoingPacket(void *pOut, int cbMaxOut, unsigned int *pNetAdr, unsigned short *pPort) + { + return 0; + } + + void MasterServerUpdater::SetBasicServerData(unsigned short nProtocolVersion, bool bDedicatedServer, const char *pRegionName, const char *pProductName, unsigned short nMaxReportedClients, bool bPasswordProtected, const char *pGameDescription) + { + } + + void MasterServerUpdater::ClearAllKeyValues() + { + } + + void MasterServerUpdater::SetKeyValue(const char *pKey, const char *pValue) + { + } + + void MasterServerUpdater::NotifyShutdown() + { + } + + bool MasterServerUpdater::WasRestartRequested() + { + return false; + } + + void MasterServerUpdater::ForceHeartbeat() + { + } + + bool MasterServerUpdater::AddMasterServer(const char *pServerAddress) + { + return true; + } + + bool MasterServerUpdater::RemoveMasterServer(const char *pServerAddress) + { + return true; + } + + int MasterServerUpdater::GetNumMasterServers() + { + return 0; + } + + int MasterServerUpdater::GetMasterServerAddress(int iServer, char *pOut, int outBufferSize) + { + return 0; + } +} diff --git a/iw4/Steam/Interfaces/SteamMasterServerUpdater.hpp b/iw4/Steam/Interfaces/SteamMasterServerUpdater.hpp new file mode 100644 index 00000000..4ded5df5 --- /dev/null +++ b/iw4/Steam/Interfaces/SteamMasterServerUpdater.hpp @@ -0,0 +1,21 @@ +namespace Steam +{ + class MasterServerUpdater + { + public: + virtual void SetActive(bool bActive); + virtual void SetHeartbeatInterval(int iHeartbeatInterval); + virtual bool HandleIncomingPacket(const void *pData, int cbData, unsigned int srcIP, unsigned short srcPort); + virtual int GetNextOutgoingPacket(void *pOut, int cbMaxOut, unsigned int *pNetAdr, unsigned short *pPort); + virtual void SetBasicServerData(unsigned short nProtocolVersion, bool bDedicatedServer, const char *pRegionName, const char *pProductName, unsigned short nMaxReportedClients, bool bPasswordProtected, const char *pGameDescription); + virtual void ClearAllKeyValues(); + virtual void SetKeyValue(const char *pKey, const char *pValue); + virtual void NotifyShutdown(); + virtual bool WasRestartRequested(); + virtual void ForceHeartbeat(); + virtual bool AddMasterServer(const char *pServerAddress); + virtual bool RemoveMasterServer(const char *pServerAddress); + virtual int GetNumMasterServers(); + virtual int GetMasterServerAddress(int iServer, char *pOut, int outBufferSize); + }; +} diff --git a/iw4/Steam/Interfaces/SteamMatchmaking.cpp b/iw4/Steam/Interfaces/SteamMatchmaking.cpp new file mode 100644 index 00000000..d6199d93 --- /dev/null +++ b/iw4/Steam/Interfaces/SteamMatchmaking.cpp @@ -0,0 +1,170 @@ +#include "..\..\STDInclude.hpp" + +namespace Steam +{ + int Matchmaking::GetFavoriteGameCount() + { + return 0; + } + + bool Matchmaking::GetFavoriteGame(int iGame, unsigned int *pnAppID, unsigned int *pnIP, unsigned short *pnConnPort, unsigned short *pnQueryPort, unsigned int *punFlags, unsigned int *pRTime32LastPlayedOnServer) + { + return false; + } + + int Matchmaking::AddFavoriteGame(unsigned int nAppID, unsigned int nIP, unsigned short nConnPort, unsigned short nQueryPort, unsigned int unFlags, unsigned int rTime32LastPlayedOnServer) + { + return 0; + } + + bool Matchmaking::RemoveFavoriteGame(unsigned int nAppID, unsigned int nIP, unsigned short nConnPort, unsigned short nQueryPort, unsigned int unFlags) + { + return false; + } + + unsigned __int64 Matchmaking::RequestLobbyList() + { + // TODO: Implement + return 0; + } + + void Matchmaking::AddRequestLobbyListStringFilter(const char *pchKeyToMatch, const char *pchValueToMatch, int eComparisonType) + { + } + + void Matchmaking::AddRequestLobbyListNumericalFilter(const char *pchKeyToMatch, int nValueToMatch, int eComparisonType) + { + } + + void Matchmaking::AddRequestLobbyListNearValueFilter(const char *pchKeyToMatch, int nValueToBeCloseTo) + { + } + + void Matchmaking::AddRequestLobbyListFilterSlotsAvailable(int nSlotsAvailable) + { + } + + SteamID Matchmaking::GetLobbyByIndex(int iLobby) + { + return SteamID(); + } + + unsigned __int64 Matchmaking::CreateLobby(int eLobbyType, int cMaxMembers) + { + // TODO: Implement + return 0; + } + + unsigned __int64 Matchmaking::JoinLobby(SteamID steamIDLobby) + { + // TODO: Implement + return 0; + } + + void Matchmaking::LeaveLobby(SteamID steamIDLobby) + { + } + + bool Matchmaking::InviteUserToLobby(SteamID steamIDLobby, SteamID steamIDInvitee) + { + return true; + } + + int Matchmaking::GetNumLobbyMembers(SteamID steamIDLobby) + { + return 1; + } + + SteamID Matchmaking::GetLobbyMemberByIndex(SteamID steamIDLobby, int iMember) + { + return SteamID(); + } + + const char *Matchmaking::GetLobbyData(SteamID steamIDLobby, const char *pchKey) + { + return ""; + } + + bool Matchmaking::SetLobbyData(SteamID steamIDLobby, const char *pchKey, const char *pchValue) + { + return true; + } + + int Matchmaking::GetLobbyDataCount(SteamID steamIDLobby) + { + return 0; + } + + bool Matchmaking::GetLobbyDataByIndex(SteamID steamIDLobby, int iLobbyData, char *pchKey, int cchKeyBufferSize, char *pchValue, int cchValueBufferSize) + { + return false; + } + + bool Matchmaking::DeleteLobbyData(SteamID steamIDLobby, const char *pchKey) + { + return false; + } + + const char *Matchmaking::GetLobbyMemberData(SteamID steamIDLobby, SteamID steamIDUser, const char *pchKey) + { + return ""; + } + + void Matchmaking::SetLobbyMemberData(SteamID steamIDLobby, const char *pchKey, const char *pchValue) + { + } + + bool Matchmaking::SendLobbyChatMsg(SteamID steamIDLobby, const void *pvMsgBody, int cubMsgBody) + { + return true; + } + + int Matchmaking::GetLobbyChatEntry(SteamID steamIDLobby, int iChatID, SteamID *pSteamIDUser, void *pvData, int cubData, int *peChatEntryType) + { + return 0; + } + + bool Matchmaking::RequestLobbyData(SteamID steamIDLobby) + { + return false; + } + + void Matchmaking::SetLobbyGameServer(SteamID steamIDLobby, unsigned int unGameServerIP, unsigned short unGameServerPort, SteamID steamIDGameServer) + { + } + + bool Matchmaking::GetLobbyGameServer(SteamID steamIDLobby, unsigned int *punGameServerIP, unsigned short *punGameServerPort, SteamID *psteamIDGameServer) + { + return false; + } + + bool Matchmaking::SetLobbyMemberLimit(SteamID steamIDLobby, int cMaxMembers) + { + return true; + } + + int Matchmaking::GetLobbyMemberLimit(SteamID steamIDLobby) + { + return 0; + } + + bool Matchmaking::SetLobbyType(SteamID steamIDLobby, int eLobbyType) + { + return true; + } + + bool Matchmaking::SetLobbyJoinable(SteamID steamIDLobby, bool bLobbyJoinable) + { + return true; + } + + SteamID Matchmaking::GetLobbyOwner(SteamID steamIDLobby) + { + return SteamID(); + } + + bool Matchmaking::SetLobbyOwner(SteamID steamIDLobby, SteamID steamIDNewOwner) + { + return true; + } +} diff --git a/iw4/Steam/Interfaces/SteamMatchmaking.hpp b/iw4/Steam/Interfaces/SteamMatchmaking.hpp new file mode 100644 index 00000000..382643d8 --- /dev/null +++ b/iw4/Steam/Interfaces/SteamMatchmaking.hpp @@ -0,0 +1,41 @@ +namespace Steam +{ + class Matchmaking + { + public: + virtual int GetFavoriteGameCount(); + virtual bool GetFavoriteGame(int iGame, unsigned int *pnAppID, unsigned int *pnIP, unsigned short *pnConnPort, unsigned short *pnQueryPort, unsigned int *punFlags, unsigned int *pRTime32LastPlayedOnServer); + virtual int AddFavoriteGame(unsigned int nAppID, unsigned int nIP, unsigned short nConnPort, unsigned short nQueryPort, unsigned int unFlags, unsigned int rTime32LastPlayedOnServer); + virtual bool RemoveFavoriteGame(unsigned int nAppID, unsigned int nIP, unsigned short nConnPort, unsigned short nQueryPort, unsigned int unFlags); + virtual unsigned __int64 RequestLobbyList(); + virtual void AddRequestLobbyListStringFilter(const char *pchKeyToMatch, const char *pchValueToMatch, int eComparisonType); + virtual void AddRequestLobbyListNumericalFilter(const char *pchKeyToMatch, int nValueToMatch, int eComparisonType); + virtual void AddRequestLobbyListNearValueFilter(const char *pchKeyToMatch, int nValueToBeCloseTo); + virtual void AddRequestLobbyListFilterSlotsAvailable(int nSlotsAvailable); + virtual SteamID GetLobbyByIndex(int iLobby); + virtual unsigned __int64 CreateLobby(int eLobbyType, int cMaxMembers); + virtual unsigned __int64 JoinLobby(SteamID steamIDLobby); + virtual void LeaveLobby(SteamID steamIDLobby); + virtual bool InviteUserToLobby(SteamID steamIDLobby, SteamID steamIDInvitee); + virtual int GetNumLobbyMembers(SteamID steamIDLobby); + virtual SteamID GetLobbyMemberByIndex(SteamID steamIDLobby, int iMember); + virtual const char *GetLobbyData(SteamID steamIDLobby, const char *pchKey); + virtual bool SetLobbyData(SteamID steamIDLobby, const char *pchKey, const char *pchValue); + virtual int GetLobbyDataCount(SteamID steamIDLobby); + virtual bool GetLobbyDataByIndex(SteamID steamIDLobby, int iLobbyData, char *pchKey, int cchKeyBufferSize, char *pchValue, int cchValueBufferSize); + virtual bool DeleteLobbyData(SteamID steamIDLobby, const char *pchKey); + virtual const char *GetLobbyMemberData(SteamID steamIDLobby, SteamID steamIDUser, const char *pchKey); + virtual void SetLobbyMemberData(SteamID steamIDLobby, const char *pchKey, const char *pchValue); + virtual bool SendLobbyChatMsg(SteamID steamIDLobby, const void *pvMsgBody, int cubMsgBody); + virtual int GetLobbyChatEntry(SteamID steamIDLobby, int iChatID, SteamID *pSteamIDUser, void *pvData, int cubData, int *peChatEntryType); + virtual bool RequestLobbyData(SteamID steamIDLobby); + virtual void SetLobbyGameServer(SteamID steamIDLobby, unsigned int unGameServerIP, unsigned short unGameServerPort, SteamID steamIDGameServer); + virtual bool GetLobbyGameServer(SteamID steamIDLobby, unsigned int *punGameServerIP, unsigned short *punGameServerPort, SteamID *psteamIDGameServer); + virtual bool SetLobbyMemberLimit(SteamID steamIDLobby, int cMaxMembers); + virtual int GetLobbyMemberLimit(SteamID steamIDLobby); + virtual bool SetLobbyType(SteamID steamIDLobby, int eLobbyType); + virtual bool SetLobbyJoinable(SteamID steamIDLobby, bool bLobbyJoinable); + virtual SteamID GetLobbyOwner(SteamID steamIDLobby); + virtual bool SetLobbyOwner(SteamID steamIDLobby, SteamID steamIDNewOwner); + }; +} diff --git a/iw4/Steam/Interfaces/SteamNetworking.cpp b/iw4/Steam/Interfaces/SteamNetworking.cpp new file mode 100644 index 00000000..7788026d --- /dev/null +++ b/iw4/Steam/Interfaces/SteamNetworking.cpp @@ -0,0 +1,104 @@ +#include "..\..\STDInclude.hpp" + +namespace Steam +{ + bool Networking::SendP2PPacket(SteamID steamIDRemote, const void *pubData, unsigned int cubData, int eP2PSendType) + { + return false; + } + + bool Networking::IsP2PPacketAvailable(unsigned int *pcubMsgSize) + { + return false; + } + + bool Networking::ReadP2PPacket(void *pubDest, unsigned int cubDest, unsigned int *pcubMsgSize, SteamID *psteamIDRemote) + { + return false; + } + + bool Networking::AcceptP2PSessionWithUser(SteamID steamIDRemote) + { + return false; + } + + bool Networking::CloseP2PSessionWithUser(SteamID steamIDRemote) + { + return false; + } + + bool Networking::GetP2PSessionState(SteamID steamIDRemote, void *pConnectionState) + { + return false; + } + + unsigned int Networking::CreateListenSocket(int nVirtualP2PPort, unsigned int nIP, unsigned short nPort, bool bAllowUseOfPacketRelay) + { + return NULL; + } + + unsigned int Networking::CreateP2PConnectionSocket(SteamID steamIDTarget, int nVirtualPort, int nTimeoutSec, bool bAllowUseOfPacketRelay) + { + return NULL; + } + + unsigned int Networking::CreateConnectionSocket(unsigned int nIP, unsigned short nPort, int nTimeoutSec) + { + return NULL; + } + + bool Networking::DestroySocket(unsigned int hSocket, bool bNotifyRemoteEnd) + { + return false; + } + + bool Networking::DestroyListenSocket(unsigned int hSocket, bool bNotifyRemoteEnd) + { + return false; + } + + bool Networking::SendDataOnSocket(unsigned int hSocket, void *pubData, unsigned int cubData, bool bReliable) + { + return false; + } + + bool Networking::IsDataAvailableOnSocket(unsigned int hSocket, unsigned int *pcubMsgSize) + { + return false; + } + + bool Networking::RetrieveDataFromSocket(unsigned int hSocket, void *pubDest, unsigned int cubDest, unsigned int *pcubMsgSize) + { + return false; + } + + bool Networking::IsDataAvailable(unsigned int hListenSocket, unsigned int *pcubMsgSize, unsigned int *phSocket) + { + return false; + } + + bool Networking::RetrieveData(unsigned int hListenSocket, void *pubDest, unsigned int cubDest, unsigned int *pcubMsgSize, unsigned int *phSocket) + { + return false; + } + + bool Networking::GetSocketInfo(unsigned int hSocket, SteamID *pSteamIDRemote, int *peSocketStatus, unsigned int *punIPRemote, unsigned short *punPortRemote) + { + return false; + } + + bool Networking::GetListenSocketInfo(unsigned int hListenSocket, unsigned int *pnIP, unsigned short *pnPort) + { + return false; + } + + int Networking::GetSocketConnectionType(unsigned int hSocket) + { + return 0; + } + + int Networking::GetMaxPacketSize(unsigned int hSocket) + { + return 0; + } +} diff --git a/iw4/Steam/Interfaces/SteamNetworking.hpp b/iw4/Steam/Interfaces/SteamNetworking.hpp new file mode 100644 index 00000000..88bc001f --- /dev/null +++ b/iw4/Steam/Interfaces/SteamNetworking.hpp @@ -0,0 +1,27 @@ +namespace Steam +{ + class Networking + { + public: + virtual bool SendP2PPacket(SteamID steamIDRemote, const void *pubData, unsigned int cubData, int eP2PSendType); + virtual bool IsP2PPacketAvailable(unsigned int *pcubMsgSize); + virtual bool ReadP2PPacket(void *pubDest, unsigned int cubDest, unsigned int *pcubMsgSize, SteamID *psteamIDRemote); + virtual bool AcceptP2PSessionWithUser(SteamID steamIDRemote); + virtual bool CloseP2PSessionWithUser(SteamID steamIDRemote); + virtual bool GetP2PSessionState(SteamID steamIDRemote, void *pConnectionState); + virtual unsigned int CreateListenSocket(int nVirtualP2PPort, unsigned int nIP, unsigned short nPort, bool bAllowUseOfPacketRelay); + virtual unsigned int CreateP2PConnectionSocket(SteamID steamIDTarget, int nVirtualPort, int nTimeoutSec, bool bAllowUseOfPacketRelay); + virtual unsigned int CreateConnectionSocket(unsigned int nIP, unsigned short nPort, int nTimeoutSec); + virtual bool DestroySocket(unsigned int hSocket, bool bNotifyRemoteEnd); + virtual bool DestroyListenSocket(unsigned int hSocket, bool bNotifyRemoteEnd); + virtual bool SendDataOnSocket(unsigned int hSocket, void *pubData, unsigned int cubData, bool bReliable); + virtual bool IsDataAvailableOnSocket(unsigned int hSocket, unsigned int *pcubMsgSize); + virtual bool RetrieveDataFromSocket(unsigned int hSocket, void *pubDest, unsigned int cubDest, unsigned int *pcubMsgSize); + virtual bool IsDataAvailable(unsigned int hListenSocket, unsigned int *pcubMsgSize, unsigned int *phSocket); + virtual bool RetrieveData(unsigned int hListenSocket, void *pubDest, unsigned int cubDest, unsigned int *pcubMsgSize, unsigned int *phSocket); + virtual bool GetSocketInfo(unsigned int hSocket, SteamID *pSteamIDRemote, int *peSocketStatus, unsigned int *punIPRemote, unsigned short *punPortRemote); + virtual bool GetListenSocketInfo(unsigned int hListenSocket, unsigned int *pnIP, unsigned short *pnPort); + virtual int GetSocketConnectionType(unsigned int hSocket); + virtual int GetMaxPacketSize(unsigned int hSocket); + }; +} diff --git a/iw4/Steam/Interfaces/SteamRemoteStorage.cpp b/iw4/Steam/Interfaces/SteamRemoteStorage.cpp new file mode 100644 index 00000000..0b76153b --- /dev/null +++ b/iw4/Steam/Interfaces/SteamRemoteStorage.cpp @@ -0,0 +1,43 @@ +#include "..\..\STDInclude.hpp" + +namespace Steam +{ + bool RemoteStorage::FileWrite(const char *pchFile, const void *pvData, int cubData) + { + return true; + } + + int RemoteStorage::GetFileSize(const char *pchFile) + { + return 0; + } + + int RemoteStorage::FileRead(const char *pchFile, void *pvData, int cubDataToRead) + { + OutputDebugStringA(pchFile); + return 0; + } + + bool RemoteStorage::FileExists(const char *pchFile) + { + return false; + } + + int RemoteStorage::GetFileCount() + { + return 0; + } + + const char *RemoteStorage::GetFileNameAndSize(int iFile, int *pnFileSizeInBytes) + { + *pnFileSizeInBytes = 0; + return ""; + } + + bool RemoteStorage::GetQuota(int *pnTotalBytes, int *puAvailableBytes) + { + *pnTotalBytes = 0x10000000; + *puAvailableBytes = 0x10000000; + return false; + } +} diff --git a/iw4/Steam/Interfaces/SteamRemoteStorage.hpp b/iw4/Steam/Interfaces/SteamRemoteStorage.hpp new file mode 100644 index 00000000..d2565416 --- /dev/null +++ b/iw4/Steam/Interfaces/SteamRemoteStorage.hpp @@ -0,0 +1,14 @@ +namespace Steam +{ + class RemoteStorage + { + public: + virtual bool FileWrite(const char *pchFile, const void *pvData, int cubData); + virtual int GetFileSize(const char *pchFile); + virtual int FileRead(const char *pchFile, void *pvData, int cubDataToRead); + virtual bool FileExists(const char *pchFile); + virtual int GetFileCount(); + virtual const char *GetFileNameAndSize(int iFile, int *pnFileSizeInBytes); + virtual bool GetQuota(int *pnTotalBytes, int *puAvailableBytes); + }; +} diff --git a/iw4/Steam/Interfaces/SteamUser.cpp b/iw4/Steam/Interfaces/SteamUser.cpp new file mode 100644 index 00000000..b0f56bef --- /dev/null +++ b/iw4/Steam/Interfaces/SteamUser.cpp @@ -0,0 +1,81 @@ +#include "..\..\STDInclude.hpp" + +namespace Steam +{ + int User::GetHSteamUser() + { + return NULL; + } + + bool User::LoggedOn() + { + return true; + } + + SteamID User::GetSteamID() + { + SteamID id; + id.m_Bits = 0x110000100000000 | 0x1337; + return id; + } + + int User::InitiateGameConnection(void *pAuthBlob, int cbMaxAuthBlob, SteamID steamIDGameServer, unsigned int unIPServer, unsigned short usPortServer, bool bSecure) + { + // TODO: Generate auth ticket! + return 0; + } + + void User::TerminateGameConnection(unsigned int unIPServer, unsigned short usPortServer) + { + } + + void User::TrackAppUsageEvent(SteamID gameID, int eAppUsageEvent, const char *pchExtraInfo) + { + } + + bool User::GetUserDataFolder(char *pchBuffer, int cubBuffer) + { + return false; + } + + void User::StartVoiceRecording() + { + } + + void User::StopVoiceRecording() + { + } + + int User::GetCompressedVoice(void *pDestBuffer, unsigned int cbDestBufferSize, unsigned int *nBytesWritten) + { + return 0; + } + + int User::DecompressVoice(void *pCompressed, unsigned int cbCompressed, void *pDestBuffer, unsigned int cbDestBufferSize, unsigned int *nBytesWritten) + { + return 0; + } + + unsigned int User::GetAuthSessionTicket(void *pTicket, int cbMaxTicket, unsigned int *pcbTicket) + { + return 0; + } + + int User::BeginAuthSession(const void *pAuthTicket, int cbAuthTicket, SteamID steamID) + { + return 0; + } + + void User::EndAuthSession(SteamID steamID) + { + } + + void User::CancelAuthTicket(unsigned int hAuthTicket) + { + } + + unsigned int User::UserHasLicenseForApp(SteamID steamID, unsigned int appID) + { + return 1; + } +} diff --git a/iw4/Steam/Interfaces/SteamUser.hpp b/iw4/Steam/Interfaces/SteamUser.hpp new file mode 100644 index 00000000..7d6140ce --- /dev/null +++ b/iw4/Steam/Interfaces/SteamUser.hpp @@ -0,0 +1,24 @@ +namespace Steam +{ + class User + { + public: + virtual int GetHSteamUser(); + virtual bool LoggedOn(); + virtual SteamID GetSteamID(); + + virtual int InitiateGameConnection(void *pAuthBlob, int cbMaxAuthBlob, SteamID steamIDGameServer, unsigned int unIPServer, unsigned short usPortServer, bool bSecure); + virtual void TerminateGameConnection(unsigned int unIPServer, unsigned short usPortServer); + virtual void TrackAppUsageEvent(SteamID gameID, int eAppUsageEvent, const char *pchExtraInfo = ""); + virtual bool GetUserDataFolder(char *pchBuffer, int cubBuffer); + virtual void StartVoiceRecording(); + virtual void StopVoiceRecording(); + virtual int GetCompressedVoice(void *pDestBuffer, unsigned int cbDestBufferSize, unsigned int *nBytesWritten); + virtual int DecompressVoice(void *pCompressed, unsigned int cbCompressed, void *pDestBuffer, unsigned int cbDestBufferSize, unsigned int *nBytesWritten); + virtual unsigned int GetAuthSessionTicket(void *pTicket, int cbMaxTicket, unsigned int *pcbTicket); + virtual int BeginAuthSession(const void *pAuthTicket, int cbAuthTicket, SteamID steamID); + virtual void EndAuthSession(SteamID steamID); + virtual void CancelAuthTicket(unsigned int hAuthTicket); + virtual unsigned int UserHasLicenseForApp(SteamID steamID, unsigned int appID); + }; +} diff --git a/iw4/Steam/Interfaces/SteamUtils.cpp b/iw4/Steam/Interfaces/SteamUtils.cpp new file mode 100644 index 00000000..87abdcaa --- /dev/null +++ b/iw4/Steam/Interfaces/SteamUtils.cpp @@ -0,0 +1,96 @@ +#include "..\..\STDInclude.hpp" + +namespace Steam +{ + unsigned int Utils::GetSecondsSinceAppActive() + { + return 0; + } + + unsigned int Utils::GetSecondsSinceComputerActive() + { + return 0; + } + + int Utils::GetConnectedUniverse() + { + return 1; + } + + unsigned int Utils::GetServerRealTime() + { + return 0; + } + + const char* Utils::GetIPCountry() + { + return "US"; + } + + bool Utils::GetImageSize(int iImage, unsigned int *pnWidth, unsigned int *pnHeight) + { + return false; + } + + bool Utils::GetImageRGBA(int iImage, unsigned char *pubDest, int nDestBufferSize) + { + return false; + } + + bool Utils::GetCSERIPPort(unsigned int *unIP, unsigned short *usPort) + { + return false; + } + + unsigned char Utils::GetCurrentBatteryPower() + { + return 255; + } + + unsigned int Utils::GetAppID() + { + return 10190; + } + + void Utils::SetOverlayNotificationPosition(int eNotificationPosition) + { + } + + bool Utils::IsAPICallCompleted(unsigned __int64 hSteamAPICall, bool *pbFailed) + { + return false; + } + + int Utils::GetAPICallFailureReason(unsigned __int64 hSteamAPICall) + { + return -1; + } + + bool Utils::GetAPICallResult(unsigned __int64 hSteamAPICall, void *pCallback, int cubCallback, int iCallbackExpected, bool *pbFailed) + { + return false; + } + + void Utils::RunFrame() + { + } + + unsigned int Utils::GetIPCCallCount() + { + return 0; + } + + void Utils::SetWarningMessageHook(void(*pFunction)(int hpipe, const char *message)) + { + } + + bool Utils::IsOverlayEnabled() + { + return false; + } + + bool Utils::BOverlayNeedsPresent() + { + return false; + } +} diff --git a/iw4/Steam/Interfaces/SteamUtils.hpp b/iw4/Steam/Interfaces/SteamUtils.hpp new file mode 100644 index 00000000..44b8e009 --- /dev/null +++ b/iw4/Steam/Interfaces/SteamUtils.hpp @@ -0,0 +1,26 @@ +namespace Steam +{ + class Utils + { + public: + virtual unsigned int GetSecondsSinceAppActive(); + virtual unsigned int GetSecondsSinceComputerActive(); + virtual int GetConnectedUniverse(); + virtual unsigned int GetServerRealTime(); + virtual const char *GetIPCountry(); + virtual bool GetImageSize(int iImage, unsigned int *pnWidth, unsigned int *pnHeight); + virtual bool GetImageRGBA(int iImage, unsigned char *pubDest, int nDestBufferSize); + virtual bool GetCSERIPPort(unsigned int *unIP, unsigned short *usPort); + virtual unsigned char GetCurrentBatteryPower(); + virtual unsigned int GetAppID(); + virtual void SetOverlayNotificationPosition(int eNotificationPosition); + virtual bool IsAPICallCompleted(unsigned __int64 hSteamAPICall, bool *pbFailed); + virtual int GetAPICallFailureReason(unsigned __int64 hSteamAPICall); + virtual bool GetAPICallResult(unsigned __int64 hSteamAPICall, void *pCallback, int cubCallback, int iCallbackExpected, bool *pbFailed); + virtual void RunFrame(); + virtual unsigned int GetIPCCallCount(); + virtual void SetWarningMessageHook(void(*pFunction)(int hpipe, const char *message)); + virtual bool IsOverlayEnabled(); + virtual bool BOverlayNeedsPresent(); + }; +} diff --git a/iw4/Steam/Steam.cpp b/iw4/Steam/Steam.cpp new file mode 100644 index 00000000..8a0bfca5 --- /dev/null +++ b/iw4/Steam/Steam.cpp @@ -0,0 +1,100 @@ +#include "..\STDInclude.hpp" +#include "Steam.hpp" + +namespace Steam +{ + extern "C" + { + bool SteamAPI_Init() + { + return true; + } + + void SteamAPI_RegisterCallResult() + { + } + + void SteamAPI_RegisterCallback() + { + } + + void SteamAPI_RunCallbacks() + { + } + + void SteamAPI_Shutdown() + { + } + + void SteamAPI_UnregisterCallResult() + { + } + + void SteamAPI_UnregisterCallback() + { + } + + + bool SteamGameServer_Init() + { + return true; + } + + void SteamGameServer_RunCallbacks() + { + } + + void SteamGameServer_Shutdown() + { + } + + + Steam::Friends* SteamFriends() + { + static Steam::Friends iFriends; + return &iFriends; + } + + Steam::Matchmaking* SteamMatchmaking() + { + static Steam::Matchmaking iMatchmaking; + return &iMatchmaking; + } + + Steam::GameServer* SteamGameServer() + { + static Steam::GameServer iGameServer; + return &iGameServer; + } + + Steam::MasterServerUpdater* SteamMasterServerUpdater() + { + static Steam::MasterServerUpdater iMasterServerUpdater; + return &iMasterServerUpdater; + } + + Steam::Networking* SteamNetworking() + { + static Steam::Networking iNetworking; + return &iNetworking; + } + + Steam::RemoteStorage* SteamRemoteStorage() + { + static Steam::RemoteStorage iRemoteStorage; + return &iRemoteStorage; + } + + Steam::User* SteamUser() + { + static Steam::User iUser; + return &iUser; + } + + Steam::Utils* SteamUtils() + { + static Steam::Utils iUtils; + return &iUtils; + } + } +} diff --git a/iw4/Steam/Steam.hpp b/iw4/Steam/Steam.hpp new file mode 100644 index 00000000..341b0332 --- /dev/null +++ b/iw4/Steam/Steam.hpp @@ -0,0 +1,49 @@ +#pragma once + +#define STEAM_EXPORT extern "C" __declspec(dllexport) + +typedef union +{ + struct SteamIDComponent_t + { + unsigned int m_unAccountID : 32; + unsigned int m_unAccountInstance : 20; + unsigned int m_EAccountType : 4; + int m_EUniverse : 8; + } m_comp; + + unsigned long long m_Bits; +} SteamID; + +#include "Interfaces\SteamUser.hpp" +#include "Interfaces\SteamUtils.hpp" +#include "Interfaces\SteamFriends.hpp" +#include "Interfaces\SteamGameServer.hpp" +#include "Interfaces\SteamNetworking.hpp" +#include "Interfaces\SteamMatchmaking.hpp" +#include "Interfaces\SteamRemoteStorage.hpp" +#include "Interfaces\SteamMasterServerUpdater.hpp" + +namespace Steam +{ + STEAM_EXPORT bool SteamAPI_Init(); + STEAM_EXPORT void SteamAPI_RegisterCallResult(); + STEAM_EXPORT void SteamAPI_RegisterCallback(); + STEAM_EXPORT void SteamAPI_RunCallbacks(); + STEAM_EXPORT void SteamAPI_Shutdown(); + STEAM_EXPORT void SteamAPI_UnregisterCallResult(); + STEAM_EXPORT void SteamAPI_UnregisterCallback(); + + STEAM_EXPORT bool SteamGameServer_Init(); + STEAM_EXPORT void SteamGameServer_RunCallbacks(); + STEAM_EXPORT void SteamGameServer_Shutdown(); + + STEAM_EXPORT Steam::Friends* SteamFriends(); + STEAM_EXPORT Steam::Matchmaking* SteamMatchmaking(); + STEAM_EXPORT Steam::GameServer* SteamGameServer(); + STEAM_EXPORT Steam::MasterServerUpdater* SteamMasterServerUpdater(); + STEAM_EXPORT Steam::Networking* SteamNetworking(); + STEAM_EXPORT Steam::RemoteStorage* SteamRemoteStorage(); + STEAM_EXPORT Steam::User* SteamUser(); + STEAM_EXPORT Steam::Utils* SteamUtils(); +} diff --git a/iw4/Utils/Hooking.cpp b/iw4/Utils/Hooking.cpp new file mode 100644 index 00000000..4dfd52b7 --- /dev/null +++ b/iw4/Utils/Hooking.cpp @@ -0,0 +1,109 @@ +#include "..\STDInclude.hpp" + +namespace Utils +{ + Hook::~Hook() + { + if (Hook::Initialized) + { + Hook::Uninstall(); + } + } + + Hook* Hook::Initialize(DWORD place, void* stub, bool useJump) + { + return Hook::Initialize((void*)place, stub, useJump); + } + + Hook* Hook::Initialize(void* place, void* stub, bool useJump) + { + if (Hook::Initialized) return this; + Hook::Initialized = true; + + Hook::UseJump = useJump; + Hook::Place = place; + Hook::Stub = stub; + + return this; + } + + Hook* Hook::Install() + { + Hook::StateMutex.lock(); + + if (!Hook::Initialized || Hook::Installed) + { + Hook::StateMutex.unlock(); + return this; + } + + Hook::Installed = true; + + DWORD d; + VirtualProtect(Hook::Place, sizeof(Hook::Buffer), PAGE_EXECUTE_READWRITE, &d); + memcpy(Hook::Buffer, Hook::Place, sizeof(Hook::Buffer)); + + char* Code = (char*)Hook::Place; + + *Code = (char)(Hook::UseJump ? 0xE9 : 0xE8); + + *(size_t*)&Code[1] = (size_t)Hook::Stub - ((size_t)Hook::Place + 5); + + VirtualProtect(Hook::Place, sizeof(Hook::Buffer), d, &d); + + FlushInstructionCache(GetCurrentProcess(), Hook::Place, sizeof(Hook::Buffer)); + + Hook::StateMutex.unlock(); + + return this; + } + + void Hook::Quick() + { + if (Hook::Installed) + { + Hook::Installed = false; + } + } + + Hook* Hook::Uninstall() + { + Hook::StateMutex.lock(); + + if (!Hook::Initialized || !Hook::Installed) + { + Hook::StateMutex.unlock(); + return this; + } + + Hook::Installed = false; + + DWORD d; + VirtualProtect(Hook::Place, sizeof(Hook::Buffer), PAGE_EXECUTE_READWRITE, &d); + + memcpy(Hook::Place, Hook::Buffer, sizeof(Hook::Buffer)); + + VirtualProtect(Hook::Place, sizeof(Hook::Buffer), d, &d); + + FlushInstructionCache(GetCurrentProcess(), Hook::Place, sizeof(Hook::Buffer)); + + Hook::StateMutex.unlock(); + + return this; + } + + void* Hook::GetAddress() + { + return Hook::Place; + } + + void Hook::Nop(void* place, size_t length) + { + memset(place, 0x90, length); + } + + void Hook::Nop(DWORD place, size_t length) + { + Nop((void*)place, length); + } +} diff --git a/iw4/Utils/Hooking.hpp b/iw4/Utils/Hooking.hpp new file mode 100644 index 00000000..dcdbb7d9 --- /dev/null +++ b/iw4/Utils/Hooking.hpp @@ -0,0 +1,60 @@ +#pragma once + +#define HOOK_JUMP true +#define HOOK_CALL false + +namespace Utils +{ + class Hook + { + public: + Hook() : Place(nullptr), Stub(nullptr), Initialized(false), Installed(false), UseJump(false) { ZeroMemory(Hook::Buffer, sizeof(Hook::Buffer)); } + Hook(void* place, void* stub, bool useJump = true) : Hook() { Hook::Initialize(place, stub, useJump); } + Hook(DWORD place, void* stub, bool useJump = true) : Hook((void*)place, stub, useJump) {} + + ~Hook(); + + Hook* Initialize(void* place, void* stub, bool useJump = true); + Hook* Initialize(DWORD place, void* stub, bool useJump = true); + Hook* Install(); + Hook* Uninstall(); + + void* GetAddress(); + void Quick(); + + static void Nop(void* place, size_t length); + static void Nop(DWORD place, size_t length); + + template static void Set(void* place, T value) + { + *(T*)place = value; + FlushInstructionCache(GetCurrentProcess(), place, sizeof(T)); + } + + template static void Set(DWORD place, T value) + { + return Set((void*)place, value); + } + + template static T Get(void* place) + { + return *(T*)place; + } + + template static T Get(DWORD place) + { + return Get((void*)place); + } + + private: + bool Initialized; + bool Installed; + + void* Place; + void* Stub; + char Buffer[5]; + bool UseJump; + + std::mutex StateMutex; + }; +} diff --git a/iw4/Utils/Utils.cpp b/iw4/Utils/Utils.cpp new file mode 100644 index 00000000..5dcce60d --- /dev/null +++ b/iw4/Utils/Utils.cpp @@ -0,0 +1,27 @@ +#include "..\STDInclude.hpp" + +#define VA_BUFFER_COUNT 4 +#define VA_BUFFER_SIZE 4096 + +namespace Utils +{ + const char *VA(const char *fmt, ...) + { + static char g_vaBuffer[VA_BUFFER_COUNT][VA_BUFFER_SIZE]; + static int g_vaNextBufferIndex = 0; + + va_list ap; + va_start(ap, fmt); + char* dest = g_vaBuffer[g_vaNextBufferIndex]; + vsprintf_s(g_vaBuffer[g_vaNextBufferIndex], fmt, ap); + g_vaNextBufferIndex = (g_vaNextBufferIndex + 1) % VA_BUFFER_COUNT; + va_end(ap); + return dest; + } + + std::string StrToLower(std::string input) + { + std::transform(input.begin(), input.end(), input.begin(), ::tolower); + return input; + } +} \ No newline at end of file diff --git a/iw4/Utils/Utils.hpp b/iw4/Utils/Utils.hpp new file mode 100644 index 00000000..8cd9bfa4 --- /dev/null +++ b/iw4/Utils/Utils.hpp @@ -0,0 +1,5 @@ +namespace Utils +{ + const char *VA(const char *fmt, ...); + std::string StrToLower(std::string input); +} diff --git a/iw4/iw4.vcxproj b/iw4/iw4.vcxproj new file mode 100644 index 00000000..fafb9280 --- /dev/null +++ b/iw4/iw4.vcxproj @@ -0,0 +1,107 @@ + + + + + Release + Win32 + + + + {38B4FC13-CEBC-4099-8698-3E62943C1EAA} + Win32Proj + iw4 + + + + DynamicLibrary + false + v120 + true + MultiByte + + + + + + + + + + false + iw4m + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;IW4_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + copy /y "$(TargetPath)" "D:\Games\SteamLibrary\steamapps\common\Call of Duty Modern Warfare 2\" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + + + \ No newline at end of file diff --git a/iw4/iw4.vcxproj.filters b/iw4/iw4.vcxproj.filters new file mode 100644 index 00000000..b2d0c501 --- /dev/null +++ b/iw4/iw4.vcxproj.filters @@ -0,0 +1,164 @@ + + + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {c97341f6-b778-4acf-bdce-24c602206b5a} + + + {d46d7650-0188-47ba-865f-c78e5b7e9910} + + + {88e00811-087a-4881-8abf-5e8eb4695a3b} + + + {3e48fe95-8760-4a3d-b4b7-5b9b3025886d} + + + {ff889d4b-f01e-4c7f-9ba8-39ab0326c32b} + + + {42cf4b9a-e10a-4c28-ac06-2bfa9e259784} + + + + + Source + + + Source\Steam\Interfaces + + + Source\Steam\Interfaces + + + Source\Steam\Interfaces + + + Source\Steam\Interfaces + + + Source\Steam\Interfaces + + + Source\Steam\Interfaces + + + Source\Steam\Interfaces + + + Source\Steam\Interfaces + + + Source\Utils + + + Source\Utils + + + Source\Components + + + Source\Components\Modules + + + Source\Components\Modules + + + Source\Game + + + Source\Steam + + + Source\Components\Modules + + + Source\Components\Modules + + + Source\Components\Modules + + + Source\Components\Modules + + + Source\Components\Modules + + + + + Source\Steam\Interfaces + + + Source\Steam\Interfaces + + + Source\Steam\Interfaces + + + Source\Steam\Interfaces + + + Source\Steam\Interfaces + + + Source\Steam\Interfaces + + + Source\Steam\Interfaces + + + Source\Steam\Interfaces + + + Source\Utils + + + Source\Utils + + + Source\Components + + + Source\Components\Modules + + + Source\Components\Modules + + + Source\Game + + + Source\Game + + + Source\Steam + + + Source\Components\Modules + + + Source + + + Source\Components\Modules + + + Source\Components\Modules + + + Source\Components\Modules + + + Source\Components\Modules + + + \ No newline at end of file diff --git a/iw4/iw4.vcxproj.user b/iw4/iw4.vcxproj.user new file mode 100644 index 00000000..7cccaf23 --- /dev/null +++ b/iw4/iw4.vcxproj.user @@ -0,0 +1,8 @@ + + + + iw4m.exe + D:\Games\SteamLibrary\steamapps\common\Call of Duty Modern Warfare 2\ + WindowsLocalDebugger + + \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 00000000..fe821ca8 --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "name": "iw4", + "version": "1.0.0", + "description": "", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" +}