diff --git a/src/compat.h b/src/compat.h new file mode 100644 index 0000000..17e37fb --- /dev/null +++ b/src/compat.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +// Backport of `std::make_unique` for the Xbox 360 toolchain. +// +// The Xenon compiler provides std::unique_ptr but does not support: +// - `std::make_unique` (introduced in C++14) +// - variadic templates (required by the real make_unique) +template inline std::unique_ptr make_unique() +{ + return std::unique_ptr(new T()); +} diff --git a/src/game/iw2/mp/main.cpp b/src/game/iw2/mp/main.cpp index b8dbdb7..524cec9 100644 --- a/src/game/iw2/mp/main.cpp +++ b/src/game/iw2/mp/main.cpp @@ -17,9 +17,5 @@ IW2_MP_Plugin::~IW2_MP_Plugin() { } -bool IW2_MP_Plugin::ShouldLoad() -{ - return (strncmp((char *)0x820410E4, "multiplayer", 11) == 0); -} } // namespace mp } // namespace iw2 diff --git a/src/game/iw2/mp/main.h b/src/game/iw2/mp/main.h index 02368c0..16850e5 100644 --- a/src/game/iw2/mp/main.h +++ b/src/game/iw2/mp/main.h @@ -12,7 +12,6 @@ class IW2_MP_Plugin : public Plugin public: IW2_MP_Plugin(); ~IW2_MP_Plugin(); - static bool ShouldLoad(); }; } // namespace mp } // namespace iw2 diff --git a/src/game/iw2/sp/main.cpp b/src/game/iw2/sp/main.cpp index d23cb9a..ab5c609 100644 --- a/src/game/iw2/sp/main.cpp +++ b/src/game/iw2/sp/main.cpp @@ -17,11 +17,5 @@ IW2_SP_Plugin::~IW2_SP_Plugin() { } -bool IW2_SP_Plugin::ShouldLoad() -{ - // Check if the game is in single player mode - return (strncmp((char *)0x82059FE0, "startSingleplayer", 17) == 0); -} - } // namespace sp } // namespace iw2 diff --git a/src/game/iw2/sp/main.h b/src/game/iw2/sp/main.h index 5673f76..c58d3f5 100644 --- a/src/game/iw2/sp/main.h +++ b/src/game/iw2/sp/main.h @@ -10,7 +10,6 @@ class IW2_SP_Plugin : public Plugin public: IW2_SP_Plugin(); ~IW2_SP_Plugin(); - static bool ShouldLoad(); }; } // namespace sp } // namespace iw2 diff --git a/src/game/iw3/mp/main.cpp b/src/game/iw3/mp/main.cpp index 00fc794..a8b200b 100644 --- a/src/game/iw3/mp/main.cpp +++ b/src/game/iw3/mp/main.cpp @@ -1607,10 +1607,5 @@ IW3_MP_Plugin::~IW3_MP_Plugin() Pmove_Detour.Remove(); } -bool IW3_MP_Plugin::ShouldLoad() -{ - return (strncmp((char *)0x82032AC4, "multiplayer", 11) == 0); -} - } // namespace mp } // namespace iw3 diff --git a/src/game/iw3/mp/main.h b/src/game/iw3/mp/main.h index af389c4..e1be566 100644 --- a/src/game/iw3/mp/main.h +++ b/src/game/iw3/mp/main.h @@ -12,7 +12,6 @@ class IW3_MP_Plugin : public Plugin public: IW3_MP_Plugin(); ~IW3_MP_Plugin(); - static bool ShouldLoad(); }; } // namespace mp } // namespace iw3 diff --git a/src/game/iw3/sp/main.cpp b/src/game/iw3/sp/main.cpp index f4e60c9..9394811 100644 --- a/src/game/iw3/sp/main.cpp +++ b/src/game/iw3/sp/main.cpp @@ -159,10 +159,5 @@ IW3_SP_Plugin::~IW3_SP_Plugin() Load_MapEntsPtr_Detour.Remove(); } -bool IW3_SP_Plugin::ShouldLoad() -{ - return (strncmp((char *)0x82065E48, "startSingleplayer", 17) == 0); -} - } // namespace sp } // namespace iw3 diff --git a/src/game/iw3/sp/main.h b/src/game/iw3/sp/main.h index 07ba6ea..61a03de 100644 --- a/src/game/iw3/sp/main.h +++ b/src/game/iw3/sp/main.h @@ -8,7 +8,6 @@ class IW3_SP_Plugin : public Plugin public: IW3_SP_Plugin(); ~IW3_SP_Plugin(); - static bool ShouldLoad(); }; } // namespace sp } // namespace iw3 diff --git a/src/game/iw4/mp/main.cpp b/src/game/iw4/mp/main.cpp index 1913a35..97d55b2 100644 --- a/src/game/iw4/mp/main.cpp +++ b/src/game/iw4/mp/main.cpp @@ -30,11 +30,5 @@ IW4_MP_Plugin::IW4_MP_Plugin() RegisterModule(new scr_parser()); } -bool IW4_MP_Plugin::ShouldLoad() -{ - DbgPrint("IW4 MP: Checking if plugin should load\n"); - return (strncmp((char *)0x82001F44, "multiplayer", 11) == 0); -} - } // namespace mp } // namespace iw4 diff --git a/src/game/iw4/mp/main.h b/src/game/iw4/mp/main.h index 1e6d47f..22c58e4 100644 --- a/src/game/iw4/mp/main.h +++ b/src/game/iw4/mp/main.h @@ -10,7 +10,6 @@ class IW4_MP_Plugin : public Plugin public: IW4_MP_Plugin(); - static bool ShouldLoad(); }; } // namespace mp } // namespace iw4 diff --git a/src/game/iw4/sp/main.cpp b/src/game/iw4/sp/main.cpp index 24192be..3e71329 100644 --- a/src/game/iw4/sp/main.cpp +++ b/src/game/iw4/sp/main.cpp @@ -42,11 +42,5 @@ IW4_SP_Plugin::IW4_SP_Plugin() RegisterModule(new scr_parser()); } -bool IW4_SP_Plugin::ShouldLoad() -{ - DbgPrint("IW4 SP: Checking if plugin should load\n"); - return (strncmp((char *)0x8203C924, "startSingleplayer", 17) == 0); -} - } // namespace sp } // namespace iw4 diff --git a/src/game/iw4/sp/main.h b/src/game/iw4/sp/main.h index b004dd9..1eb861e 100644 --- a/src/game/iw4/sp/main.h +++ b/src/game/iw4/sp/main.h @@ -10,7 +10,6 @@ class IW4_SP_Plugin : public Plugin public: IW4_SP_Plugin(); - static bool ShouldLoad(); }; } // namespace sp } // namespace iw4 diff --git a/src/game/iw5/mp/main.cpp b/src/game/iw5/mp/main.cpp index df89e3d..10e1be4 100644 --- a/src/game/iw5/mp/main.cpp +++ b/src/game/iw5/mp/main.cpp @@ -222,9 +222,5 @@ IW5_MP_Plugin::~IW5_MP_Plugin() DB_IsXAssetDefault_Detour.Remove(); } -bool IW5_MP_Plugin::ShouldLoad() -{ - return (strncmp((char *)0x82001458, "multiplayer", 11) == 0); -} } // namespace mp } // namespace iw5 diff --git a/src/game/iw5/mp/main.h b/src/game/iw5/mp/main.h index 993a968..8445334 100644 --- a/src/game/iw5/mp/main.h +++ b/src/game/iw5/mp/main.h @@ -12,7 +12,6 @@ class IW5_MP_Plugin : public Plugin public: IW5_MP_Plugin(); ~IW5_MP_Plugin(); - static bool ShouldLoad(); }; } // namespace mp } // namespace iw5 diff --git a/src/game/qos/mp/main.cpp b/src/game/qos/mp/main.cpp index fd6406e..727f3c4 100644 --- a/src/game/qos/mp/main.cpp +++ b/src/game/qos/mp/main.cpp @@ -15,10 +15,5 @@ QOS_MP_Plugin::QOS_MP_Plugin() RegisterModule(new scr_parser()); } -bool QOS_MP_Plugin::ShouldLoad() -{ - return strncmp((char *)0x8200236C, "multiplayer", 11) == 0; -} - } // namespace mp } // namespace qos diff --git a/src/game/qos/mp/main.h b/src/game/qos/mp/main.h index ff542c2..a4d69ac 100644 --- a/src/game/qos/mp/main.h +++ b/src/game/qos/mp/main.h @@ -9,7 +9,6 @@ class QOS_MP_Plugin : public Plugin public: QOS_MP_Plugin(); - static bool ShouldLoad(); }; } // namespace mp } // namespace qos diff --git a/src/game/qos/sp/main.cpp b/src/game/qos/sp/main.cpp index 24ff66d..35daea6 100644 --- a/src/game/qos/sp/main.cpp +++ b/src/game/qos/sp/main.cpp @@ -12,10 +12,5 @@ QOS_SP_Plugin::QOS_SP_Plugin() RegisterModule(new scr_parser()); } -bool QOS_SP_Plugin::ShouldLoad() -{ - return strncmp((char *)0x82047EC4, "startSingleplayer", 17) == 0; -} - } // namespace sp } // namespace qos diff --git a/src/game/qos/sp/main.h b/src/game/qos/sp/main.h index 488e111..1f2a1e9 100644 --- a/src/game/qos/sp/main.h +++ b/src/game/qos/sp/main.h @@ -8,7 +8,6 @@ class QOS_SP_Plugin : public Plugin { public: QOS_SP_Plugin(); - static bool ShouldLoad(); }; } // namespace sp } // namespace qos diff --git a/src/game/t4/mp/main.cpp b/src/game/t4/mp/main.cpp index 32d0277..625a0c1 100644 --- a/src/game/t4/mp/main.cpp +++ b/src/game/t4/mp/main.cpp @@ -47,9 +47,5 @@ T4_MP_Plugin::~T4_MP_Plugin() DbgPrint("T4 MP: Plugin unloaded\n"); } -bool T4_MP_Plugin::ShouldLoad() -{ - return (strncmp((char *)0x820024CC, "multiplayer", 11) == 0); -} } // namespace mp } // namespace t4 diff --git a/src/game/t4/mp/main.h b/src/game/t4/mp/main.h index c206006..bc6d7c7 100644 --- a/src/game/t4/mp/main.h +++ b/src/game/t4/mp/main.h @@ -11,7 +11,6 @@ class T4_MP_Plugin : public Plugin public: T4_MP_Plugin(); ~T4_MP_Plugin(); - static bool ShouldLoad(); }; } // namespace mp diff --git a/src/game/t4/sp/main.cpp b/src/game/t4/sp/main.cpp index 84e4840..a3b3ba8 100644 --- a/src/game/t4/sp/main.cpp +++ b/src/game/t4/sp/main.cpp @@ -26,10 +26,5 @@ T4_SP_Plugin::T4_SP_Plugin() RegisterModule(new ui()); } -bool T4_SP_Plugin::ShouldLoad() -{ - return (strncmp((char *)0x82035A94, "startSingleplayer", 17) == 0); -} - } // namespace sp } // namespace t4 diff --git a/src/game/t4/sp/main.h b/src/game/t4/sp/main.h index 7b646e9..3807565 100644 --- a/src/game/t4/sp/main.h +++ b/src/game/t4/sp/main.h @@ -9,7 +9,6 @@ class T4_SP_Plugin : public Plugin { public: T4_SP_Plugin(); - static bool ShouldLoad(); }; } // namespace sp diff --git a/src/game/t5/mp/main.cpp b/src/game/t5/mp/main.cpp index e629647..09136bc 100644 --- a/src/game/t5/mp/main.cpp +++ b/src/game/t5/mp/main.cpp @@ -13,10 +13,5 @@ T5_MP_Plugin::T5_MP_Plugin() RegisterModule(new scr_parser()); } -bool T5_MP_Plugin::ShouldLoad() -{ - return strncmp((char *)0x82001998, "multiplayer", 11) == 0; -} - } // namespace mp } // namespace t5 diff --git a/src/game/t5/mp/main.h b/src/game/t5/mp/main.h index 321d894..d7febd8 100644 --- a/src/game/t5/mp/main.h +++ b/src/game/t5/mp/main.h @@ -9,7 +9,6 @@ class T5_MP_Plugin : public Plugin public: T5_MP_Plugin(); - static bool ShouldLoad(); }; } // namespace mp } // namespace t5 diff --git a/src/game/t5/sp/main.cpp b/src/game/t5/sp/main.cpp index 33c002c..b23b041 100644 --- a/src/game/t5/sp/main.cpp +++ b/src/game/t5/sp/main.cpp @@ -13,10 +13,5 @@ T5_SP_Plugin::T5_SP_Plugin() RegisterModule(new scr_parser()); } -bool T5_SP_Plugin::ShouldLoad() -{ - return strncmp((char *)0x82018364, "startSingleplayer", 17) == 0; -} - } // namespace sp } // namespace t5 diff --git a/src/game/t5/sp/main.h b/src/game/t5/sp/main.h index eefce6b..b91a6f4 100644 --- a/src/game/t5/sp/main.h +++ b/src/game/t5/sp/main.h @@ -10,7 +10,6 @@ class T5_SP_Plugin : public Plugin public: T5_SP_Plugin(); - static bool ShouldLoad(); }; } // namespace sp diff --git a/src/pch.h b/src/pch.h index 6d9174b..db4fd14 100644 --- a/src/pch.h +++ b/src/pch.h @@ -34,6 +34,7 @@ #include "xkelib.h" #include "xbox360.h" #include "plugin.h" +#include "compat.h" // Common includes #include "common/branding.h" diff --git a/src/plugin.h b/src/plugin.h index fd42167..ad9c115 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -23,9 +23,6 @@ class Plugin DbgPrint("Plugin::~Plugin\n"); }; - /* Determines if this plugin should load. */ - static bool ShouldLoad(); - void RegisterModule(Module *module) { if (module) diff --git a/src/plugin_manager.cpp b/src/plugin_manager.cpp index 884c572..49123da 100644 --- a/src/plugin_manager.cpp +++ b/src/plugin_manager.cpp @@ -1,15 +1,184 @@ #include "pch.h" #include "plugin_manager.h" -PluginManager::PluginManager() - : m_should_run(false), m_monitor_thread(nullptr), m_current_title_id(0), m_current_plugin(nullptr) +enum TitleID : DWORD { - this->InitConfig(); + NONE = 0, // Shown when loading reloading a title + DASHBOARD = 0xFFFE07D1, +}; +template std::unique_ptr CreatePlugin() +{ + return make_unique(); +} + +struct GameInfo +{ + /** + * Xbox 360 Title ID. + */ + DWORD titleId; + /** + * The XEX build timedatestamp. + */ + DWORD xexTimestamp; + /** + * The original name of the XEX. + * NOTE: This is not checked and is only for display/dev purposes. + */ + const char *moduleName; + /** + * The value of the in-game `version` dvar. + * NOTE: This is not checked and is only for display/dev purposes. + */ + const char *gameVersion; + /** + * Human friendly version. + * NOTE: This is not checked and is only for display/dev purposes. + */ + const char *friendlyVersion; + std::unique_ptr (*createPlugin)(); // nullptr = no plugin for this exe +}; + +const GameInfo GAME_INFO[] = { + { + 0x415607FF, + 0x49E8DEDE, // Fri Apr 17 20:56:14 2009 + "default_mp.xex", + "", + "007: Quantum of Solace MP Title Update #2", + &CreatePlugin, + }, + { + 0x415607FF, + 0x48D0C2CA, // Wed Sep 17 09:41:46 2008 + "default.xex", + "", + "007: Quantum of Solace SP Title Update #2", + &CreatePlugin, + }, + + { + 0x415607D1, + 0x4456B8A3, // Tue May 2 02:40:51 2006 + "default_mp.xex", + "", + "Call of Duty 2 MP Title Update #3", + &CreatePlugin, + }, + { + 0x415607D1, + 0x43E7A218, // Mon Feb 6 19:23:04 2006 + "default.xex", + "", + "Call of Duty 2 SP Title Update #3", + &CreatePlugin, + }, + { + 0x415607E6, + 0x4A78A577, // Tue Aug 4 22:17:43 2009 + "default_mp.xex", + "CoD4 MP 1.4 build 79 nightly Tue Aug 04 2009 01:51:14PM xenon", + "Call of Duty 4: Modern Warfare MP Title Update #4", + &CreatePlugin, + }, + { + 0x415607E6, + 0x46E1E82F, // Sat Sep 8 01:09:19 2007 + "default.xex", + "CoD4 1.0 build 472 nightly Fri Sep 07 2007 04:59:49PM xenon", + "Call of Duty 4: Modern Warfare SP Title Update #4", + &CreatePlugin, + }, + { + 0x4156081C, + 0x4AD7C0EE, // Fri Oct 16 01:40:14 2009 + "default_mp.xex", + "Call of Duty Multiplayer COD_WaW MP build 5.5.51 CL(0) ZQABUILD1 Thu Oct 15 17:39:03 2009 xenon", + "Call of Duty: World at War MP Title Update #7", + &CreatePlugin, + }, + { + 0x4156081C, + 0x4AD7C0DF, // Fri Oct 16 01:39:59 2009 + "default.xex", + "", + "Call of Duty: World at War SP Title Update #7", + &CreatePlugin, + }, + { + 0x41560817, + 0x4BE22338, // Thu May 6 03:02:32 2010 + "default_mp.xex", + "IW4 MP 1.4 build 669 latest Wed May 05 2010 06:55:32PM xenon", + "Call of Duty: Modern Warfare 2 MP Title Update #6", + &CreatePlugin, + }, + { + 0x41560817, + 0x5074B056, // Wed Oct 10 00:16:38 2012 + "default.xex", + "IW4 1.0 build 125545 Fri Sep 25 22:12:21 2009 xenon", + "Call of Duty: Modern Warfare 2 SP Title Update #9", + &CreatePlugin, + }, + { + 0x41560855, + 0x4E542876, // Tue Aug 23 23:23:50 2011 + "default_mp.xex", + "", + "Call of Duty: Black Ops MP Title Update #11", + &CreatePlugin, + }, + { + 0x41560855, + 0x4E542875, // Tue Aug 23 23:23:49 2011 + "default.xex", + "", + "Call of Duty: Black Ops SP Title Update #11", + &CreatePlugin, + }, + { + 0x415608CB, + 0x5B10A113, // Fri Jun 1 02:27:47 2018 + "default_mp.xex", + "IW5 MP 1.8 build 388110 Fri Sep 14 00:04:28 2012 xenon", + "Call of Duty: Modern Warfare 3 MP Title Update #24", + &CreatePlugin, + }, +}; + +const GameInfo *FindGameInfo(DWORD title_id, DWORD timestamp) +{ + for (size_t i = 0; i < ARRAYSIZE(GAME_INFO); i++) + { + if (GAME_INFO[i].titleId == title_id && GAME_INFO[i].xexTimestamp == timestamp) + { + return &GAME_INFO[i]; + } + } + return nullptr; +} + +/** + * Get the time date stamp from the current title xex. + */ +DWORD XexGetTimeDateStamp() +{ + const PLDR_DATA_TABLE_ENTRY entry = (PLDR_DATA_TABLE_ENTRY)GetModuleHandle(nullptr); + if (entry == nullptr) + { + return 0; + } + return entry->TimeDateStamp; +} + +PluginManager::PluginManager() : m_monitor_active(false), m_monitor_thread(nullptr), m_current_plugin(nullptr) +{ if (xbox::IsXenia()) { DbgPrint("[codxe][PluginManager] Running in Xenia environment, skipping plugin manager initialization.\n"); - OnTitleIDChanged(XamGetCurrentTitleId()); + OnTitleChanged(XamGetCurrentTitleId(), XexGetTimeDateStamp()); return; } @@ -20,7 +189,7 @@ PluginManager::PluginManager() PluginManager::~PluginManager() { // Signal the thread to stop and wait for it to finish - m_should_run = false; + m_monitor_active = false; if (m_monitor_thread) { WaitForSingleObject(m_monitor_thread, INFINITE); @@ -29,171 +198,74 @@ PluginManager::~PluginManager() } } -void PluginManager::InitConfig() -{ - m_title_id_configs[DASHBOARD] = TitleConfig("Dashboard", nullptr); - - m_title_id_configs[IW2] = TitleConfig("Call of Duty 2", - []() -> Plugin * - { - if (iw2::sp::IW2_SP_Plugin::ShouldLoad()) - return new iw2::sp::IW2_SP_Plugin(); - else if (iw2::mp::IW2_MP_Plugin::ShouldLoad()) - return new iw2::mp::IW2_MP_Plugin(); - else - return nullptr; - }); - - m_title_id_configs[IW3] = TitleConfig("Call of Duty 4: Modern Warfare", - []() -> Plugin * - { - if (iw3::sp::IW3_SP_Plugin::ShouldLoad()) - return new iw3::sp::IW3_SP_Plugin(); - else if (iw3::mp::IW3_MP_Plugin::ShouldLoad()) - return new iw3::mp::IW3_MP_Plugin(); - else - return nullptr; - }); - - m_title_id_configs[IW5] = TitleConfig("Call of Duty: Modern Warfare 3", - []() -> Plugin * - { - // if (iw3::sp::IW3_SP_Plugin::ShouldLoad()) - // return new iw3::sp::IW3_SP_Plugin(); - if (iw5::mp::IW5_MP_Plugin::ShouldLoad()) - return new iw5::mp::IW5_MP_Plugin(); - else - return nullptr; - }); - - m_title_id_configs[T4] = TitleConfig("Call of Duty: World at War", - []() -> Plugin * - { - if (t4::sp::T4_SP_Plugin::ShouldLoad()) - return new t4::sp::T4_SP_Plugin(); - else if (t4::mp::T4_MP_Plugin::ShouldLoad()) - return new t4::mp::T4_MP_Plugin(); - else - return nullptr; - }); - - m_title_id_configs[IW4] = TitleConfig("Call of Duty: Modern Warfare 2", - []() -> Plugin * - { - if (iw4::sp::IW4_SP_Plugin::ShouldLoad()) - return new iw4::sp::IW4_SP_Plugin(); - else if (iw4::mp::IW4_MP_Plugin::ShouldLoad()) - return new iw4::mp::IW4_MP_Plugin(); - else - return nullptr; - }); - - m_title_id_configs[T5] = TitleConfig("Call of Duty: Black Ops", - []() -> Plugin * - { - if (t5::sp::T5_SP_Plugin::ShouldLoad()) - return new t5::sp::T5_SP_Plugin(); - else if (t5::mp::T5_MP_Plugin::ShouldLoad()) - return new t5::mp::T5_MP_Plugin(); - else - return nullptr; - }); - - m_title_id_configs[QOS] = TitleConfig("007: Quantum of Solace", - []() -> Plugin * - { - if (qos::sp::QOS_SP_Plugin::ShouldLoad()) - return new qos::sp::QOS_SP_Plugin(); - else if (qos::mp::QOS_MP_Plugin::ShouldLoad()) - return new qos::mp::QOS_MP_Plugin(); - else - return nullptr; - }); -} - DWORD WINAPI PluginManager::ThreadProc(LPVOID param) { - PluginManager *manager = static_cast(param); - manager->m_should_run = true; + auto self = static_cast(param); + self->m_monitor_active = true; + + DWORD prevTitleId = 0; + DWORD prevTimestamp = 0; - while (manager->m_should_run) + while (self->m_monitor_active) { - const uint32_t current_title_id = XamGetCurrentTitleId(); - if (current_title_id != manager->m_current_title_id) + const DWORD titleId = XamGetCurrentTitleId(); + const DWORD xexTimestamp = XexGetTimeDateStamp(); + + if (titleId != prevTitleId || xexTimestamp != prevTimestamp) { - manager->OnTitleIDChanged(current_title_id); + self->OnTitleChanged(titleId, xexTimestamp); + prevTitleId = titleId; + prevTimestamp = xexTimestamp; } - - Sleep(100); // Sleep for a while to avoid busy waiting + Sleep(100); } return 0; } -PluginManager::TitleConfig *PluginManager::GetTitleConfig(TitleID title_id) -{ - auto it = m_title_id_configs.find(title_id); - if (it != m_title_id_configs.end()) - { - return &it->second; - } - return nullptr; // Return nullptr if the title ID is not found -} - -void PluginManager::OnTitleIDChanged(uint32_t title_id) +void PluginManager::OnTitleChanged(DWORD title_id, DWORD timestamp) { DbgPrint("[codxe][PluginManager] Title ID changed to: 0x%08X\n", title_id); // If there is a current plugin, clean it up if (m_current_plugin) { - DbgPrint("[codxe][PluginManager] Cleaning up current plugin for title ID: 0x%08X\n", m_current_title_id); - delete m_current_plugin; - m_current_plugin = nullptr; + DbgPrint("[codxe][PluginManager] Cleaning up current plugin\n"); + m_current_plugin.reset(); } - // Update the current title ID - m_current_title_id = title_id; - - // If running in Xenia, we might not need to wait long for the game to load - if (!xbox::IsXenia()) - { - Sleep(2000); // Allow some time for the game to load - } - - // Special case for Dashboard + // Special case if (title_id == NONE || title_id == DASHBOARD) return; - // Initialize the new title's plugins - - PluginManager::TitleConfig *config = GetTitleConfig(static_cast(title_id)); - if (!config) + const GameInfo *info = FindGameInfo(title_id, timestamp); + if (!info) { - DbgPrint("[codxe][PluginManager] No configuration found for title ID: 0x%08X\n", title_id); + DbgPrint("[codxe][PluginManager] Ignoring unknown executable Title ID:0x%08X TimeDateStamp=0x%08X\n", title_id, + timestamp); return; } - DbgPrint("[codxe][PluginManager] Found configuration for title ID: 0x%08X, name: %s\n", title_id, - config->name.c_str()); - - if (!config->create_plugin) + DbgPrint("[codxe][PluginManager] Supported game found: '%s' (%s)\n", info->friendlyVersion, info->moduleName); + if (!info->createPlugin) { - DbgPrint("[codxe][PluginManager] No plugin factory defined for title ID: 0x%08X\n", title_id); + DbgPrint("[codxe][PluginManager] No plugin for this executable.\n"); return; } - // If the title has a plugin factory, create the plugin - DbgPrint("[codxe][PluginManager] Creating plugin for title ID: 0x%08X\n", title_id); - const Plugin *plugin = config->create_plugin(); + // On Xenia we can immediately init the plugin. On the xbox wait a bit for loading + if (!xbox::IsXenia()) + { + Sleep(2000); // Allow some time for the game to load + } + + auto plugin = info->createPlugin(); if (!plugin) { - DbgPrint("[codxe][PluginManager] Failed to create plugin for title ID: 0x%08X\n", title_id); + DbgPrint("[codxe][PluginManager] Plugin factory returned nullptr.\n"); return; } - // Store the created plugin - m_current_plugin = plugin; - - DbgPrint("[codxe][PluginManager] Plugin created for title ID: 0x%08X\n", title_id); + m_current_plugin = std::move(plugin); + DbgPrint("[codxe][PluginManager] Plugin started!\n"); } diff --git a/src/plugin_manager.h b/src/plugin_manager.h index 7157640..143823f 100644 --- a/src/plugin_manager.h +++ b/src/plugin_manager.h @@ -1,49 +1,19 @@ #pragma once #include "pch.h" -#include class PluginManager { public: - enum TitleID : uint32_t - { - NONE = 0, - DASHBOARD = 0xFFFE07D1, - IW2 = 0x415607D1, - IW3 = 0x415607E6, - IW5 = 0x415608CB, - T4 = 0x4156081C, - IW4 = 0x41560817, - QOS = 0x415607FF, - T5 = 0x41560855, - }; - - struct TitleConfig - { - std::string name; - std::function create_plugin; - - TitleConfig() {}; // Default constructor for unordered_map - - TitleConfig(const std::string &title_name, std::function create_plugin) - : name(title_name), create_plugin(create_plugin) - { - } - }; - - std::unordered_map m_title_id_configs; - PluginManager(); ~PluginManager(); private: - void InitConfig(); - TitleConfig *GetTitleConfig(TitleID title_id); - bool m_should_run; + std::unique_ptr m_current_plugin; + + bool m_monitor_active; HANDLE m_monitor_thread; - uint32_t m_current_title_id; - const Plugin *m_current_plugin; - void OnTitleIDChanged(uint32_t title_id); + + void OnTitleChanged(DWORD title_id, DWORD timestamp); static DWORD WINAPI ThreadProc(LPVOID param); };