From 00336f11219ae8ca2a943434cad63ce7d5f74070 Mon Sep 17 00:00:00 2001 From: MikeIsAStar <99037623+MikeIsAStar@users.noreply.github.com> Date: Sat, 30 Mar 2024 23:00:00 -0400 Subject: [PATCH] [MKW] Allow for the "Open Host" feature to be enabled while in a room --- payload/import/mkw/net/net.hpp | 7 +- payload/import/mkw/ui/page/friendRoomPage.hpp | 79 ++++++++ payload/import/mkw/ui/page/openHostPage.hpp | 181 ++++++++++++++++++ .../import/mkw/ui/page/wifiFriendMenuPage.hpp | 161 +--------------- payload/wwfcFeature.cpp | 35 +++- 5 files changed, 298 insertions(+), 165 deletions(-) create mode 100644 payload/import/mkw/ui/page/friendRoomPage.hpp create mode 100644 payload/import/mkw/ui/page/openHostPage.hpp diff --git a/payload/import/mkw/net/net.hpp b/payload/import/mkw/net/net.hpp index bf0df18..f56d6c6 100644 --- a/payload/import/mkw/net/net.hpp +++ b/payload/import/mkw/net/net.hpp @@ -57,7 +57,7 @@ static_assert(sizeof(RacePacket) == 0x10); class NetController { public: - enum JoinType { + enum class JoinType { NotJoining = 0, WorldwideVersusRace = 1, ContinentalVersusRace = 2, @@ -116,6 +116,11 @@ class NetController return isAidTheServer(myAid()); } + bool amITheRoomHost() const + { + return m_joinType == JoinType::RoomHost; + } + bool inVanillaMatch() const { switch (m_joinType) { diff --git a/payload/import/mkw/ui/page/friendRoomPage.hpp b/payload/import/mkw/ui/page/friendRoomPage.hpp new file mode 100644 index 0000000..7189b22 --- /dev/null +++ b/payload/import/mkw/ui/page/friendRoomPage.hpp @@ -0,0 +1,79 @@ +#pragma once + +#include "import/mkw/net/net.hpp" +#include "openHostPage.hpp" + +namespace mkw::UI +{ + +#if RMC + +class FriendRoomPage : public OpenHostPage +{ +public: + void onActivate() override + { + LONGCALL void onActivate(FriendRoomPage * friendRoomPage) + AT(RMCXD_PORT(0x805D8444, 0x806289B8, 0x805D7D20, 0x805C65E0)); + + onActivate(this); + + if (mkw::Net::NetController::Instance()->amITheRoomHost()) { + OpenHostPage::onActivate(); + } + } + + void onDeactivate() override + { + LONGCALL void onDeactivate(FriendRoomPage * friendRoomPage) + AT(RMCXD_PORT(0x805D84FC, 0x80628A70, 0x805D7DD8, 0x805C6698)); + + onDeactivate(this); + + if (mkw::Net::NetController::Instance()->amITheRoomHost()) { + OpenHostPage::onDeactivate(); + } + } + + void onRefocus() override + { + LONGCALL void onRefocus(FriendRoomPage * friendRoomPage) + AT(RMCXD_PORT(0x805D8C98, 0x8062920C, 0x805D8574, 0x805C6E34)); + + onRefocus(this); + + if (mkw::Net::NetController::Instance()->amITheRoomHost()) { + OpenHostPage::onRefocus(); + } + } + +private: + /* 0x044 */ u8 _044[0xDC4 - 0x044]; +}; + +static_assert(sizeof(FriendRoomPage) == 0xDC4); + +#endif + +} // namespace mkw::UI + +#if RMC + +extern "C" { +static void FriendRoomPage_onActivate(mkw::UI::FriendRoomPage* friendRoomPage) +{ + friendRoomPage->FriendRoomPage::onActivate(); +} + +static void FriendRoomPage_onDeactivate(mkw::UI::FriendRoomPage* friendRoomPage) +{ + friendRoomPage->FriendRoomPage::onDeactivate(); +} + +static void FriendRoomPage_onRefocus(mkw::UI::FriendRoomPage* friendRoomPage) +{ + friendRoomPage->FriendRoomPage::onRefocus(); +} +} + +#endif diff --git a/payload/import/mkw/ui/page/openHostPage.hpp b/payload/import/mkw/ui/page/openHostPage.hpp new file mode 100644 index 0000000..ff613bc --- /dev/null +++ b/payload/import/mkw/ui/page/openHostPage.hpp @@ -0,0 +1,181 @@ +#pragma once + +#include "import/cxx.hpp" +#include "import/dwc.h" +#include "import/mkw/system/system.hpp" +#include "import/mkw/ui/multiMenuInputManager.hpp" +#include "import/mkw/ui/section/sectionManager.hpp" +#include "messagePopupPage.hpp" +#include "yesNoPopupPage.hpp" + +namespace mkw::UI +{ + +#if RMC + +class OpenHostPage : public Page +{ +public: + void onActivate() override + { + EGG::Heap* systemHeap = mkw::System::System::Instance().systemHeap(); + + s_onOption = + new (systemHeap, 4) MenuInputManager::Handler( + this, &OpenHostPage::onOption + ); + MultiControlInputManager* multiControlInputManager = + reinterpret_cast(menuInputManager()); + multiControlInputManager->setHandler( + MenuInputManager::InputType::Option, s_onOption + ); + + s_onYesOrNo = new (systemHeap, 4) + YesNoPage::Handler(this, &OpenHostPage::onYesOrNo); + } + + void onDeactivate() override + { + MultiControlInputManager* multiControlInputManager = + reinterpret_cast(menuInputManager()); + multiControlInputManager->setHandler( + MenuInputManager::InputType::Option, nullptr + ); + delete s_onOption; + s_onOption = nullptr; + + delete s_onYesOrNo; + s_onYesOrNo = nullptr; + } + + void onRefocus() override + { + transition(resolve()); + } + +private: + OpenHostPage(); + + enum class State { + Previous, + Prompt, + Result, + }; + + State resolve() const + { + switch (s_state) { + case State::Previous: { + break; + } + case State::Prompt: { + return State::Result; + } + case State::Result: { + return State::Previous; + } + } + + return s_state; + } + + void transition(State state) + { + Section* section = SectionManager::Instance()->currentSection(); + + if (state == s_state) { + return; + } + + switch (state) { + case State::Previous: { + break; + } + case State::Prompt: { + FormatParam formatParam{}; + formatParam.strings[0] = + L"Enable Open Host?\n\n" + L"This feature allows players who\n" + L"add your friend code to meet up with you,\n" + L"even if you don't add them back."; + + YesNoPopupPage* yesNoPopupPage = + section->page(PageId::YesNoPopup); + yesNoPopupPage->reset(); + yesNoPopupPage->setWindowMessage(0x19CA, &formatParam); + yesNoPopupPage->configureButton( + 0, 0xFAC, nullptr, Animation::None, s_onYesOrNo + ); + yesNoPopupPage->configureButton( + 1, 0xFAD, nullptr, Animation::None, s_onYesOrNo + ); + yesNoPopupPage->setDefaultChoice(1); + + push(PageId::YesNoPopup, Animation::Next); + break; + } + case State::Result: { + FormatParam formatParam{}; + if (!s_sentOpenHostValue) { + formatParam.strings[0] = L"You have lost connection to\n" + L"the server.\n\n" + L"Please try again later."; + } else { + if (s_enableOpenHost) { + formatParam.strings[0] = L"Open Host is now enabled!"; + } else { + formatParam.strings[0] = L"Open Host is now disabled!"; + } + } + + MessagePopupPage* messagePopupPage = + section->page(PageId::MessagePopup); + messagePopupPage->reset(); + messagePopupPage->setWindowMessage(0x19CA, &formatParam); + + push(PageId::MessagePopup, Animation::Next); + break; + } + } + + s_state = state; + } + + void onOption(u32 /* localPlayerId */) + { + transition(State::Prompt); + } + + void onYesOrNo(int choice, void* /* pushButton */) + { + GameSpy::GPConnection* gpConnection = DWC::stpMatchCnt->connection; + if (!gpConnection) { + s_sentOpenHostValue = false; + return; + } + s_sentOpenHostValue = true; + + bool enableOpenHost = choice == 0; + + char openHostValue[2]; + openHostValue[0] = '0' + enableOpenHost; + openHostValue[1] = '\0'; + GameSpy::gpiSendLocalInfo( + gpConnection, "\\wwfc_openhost\\", openHostValue + ); + + s_enableOpenHost = enableOpenHost; + } + + static State s_state; + static mkw::UI::MenuInputManager::Handler* s_onOption; + static mkw::UI::YesNoPage::Handler* s_onYesOrNo; + static bool s_enableOpenHost; + static bool s_sentOpenHostValue; +}; + +static_assert(sizeof(OpenHostPage) == sizeof(Page)); + +#endif + +} // namespace mkw::UI diff --git a/payload/import/mkw/ui/page/wifiFriendMenuPage.hpp b/payload/import/mkw/ui/page/wifiFriendMenuPage.hpp index a1343ea..aa07a12 100644 --- a/payload/import/mkw/ui/page/wifiFriendMenuPage.hpp +++ b/payload/import/mkw/ui/page/wifiFriendMenuPage.hpp @@ -1,20 +1,13 @@ #pragma once -#include "import/cxx.hpp" -#include "import/dwc.h" -#include "import/gamespy.h" -#include "import/mkw/system/system.hpp" -#include "import/mkw/ui/multiMenuInputManager.hpp" -#include "import/mkw/ui/section/sectionManager.hpp" -#include "messagePopupPage.hpp" -#include "yesNoPopupPage.hpp" +#include "openHostPage.hpp" namespace mkw::UI { #if RMC -class WifiFriendMenuPage : public Page +class WifiFriendMenuPage : public OpenHostPage { public: void onActivate() override @@ -24,25 +17,7 @@ class WifiFriendMenuPage : public Page onActivate(this); - // The payload is run after 'onInit' is called, so we set the handler - // here. - - EGG::Heap* systemHeap = mkw::System::System::Instance().systemHeap(); - - s_onOption = - new (systemHeap, 4) MenuInputManager::Handler( - this, &WifiFriendMenuPage::onOption - ); - MultiControlInputManager* multiControlInputManager = - reinterpret_cast(menuInputManager()); - multiControlInputManager->setHandler( - MenuInputManager::InputType::Option, s_onOption - ); - - s_onYesOrNo = - new (systemHeap, 4) YesNoPage::Handler( - this, &WifiFriendMenuPage::onYesOrNo - ); + OpenHostPage::onActivate(); } void onDeactivate() override @@ -52,16 +27,7 @@ class WifiFriendMenuPage : public Page onDeactivate(this); - MultiControlInputManager* multiControlInputManager = - reinterpret_cast(menuInputManager()); - multiControlInputManager->setHandler( - MenuInputManager::InputType::Option, nullptr - ); - delete s_onOption; - s_onOption = nullptr; - - delete s_onYesOrNo; - s_onYesOrNo = nullptr; + OpenHostPage::onDeactivate(); } void onRefocus() override @@ -71,128 +37,11 @@ class WifiFriendMenuPage : public Page Page_onRefocus(this); - transition(resolve()); + OpenHostPage::onRefocus(); } private: - enum class State { - Previous, - Prompt, - Result, - }; - - State resolve() const - { - switch (s_state) { - case State::Previous: { - break; - } - case State::Prompt: { - return State::Result; - } - case State::Result: { - return State::Previous; - } - } - - return s_state; - } - - void transition(State state) - { - Section* section = SectionManager::Instance()->currentSection(); - - if (state == s_state) { - return; - } - - switch (state) { - case State::Previous: { - break; - } - case State::Prompt: { - FormatParam formatParam{}; - formatParam.strings[0] = - L"Enable Open Host?\n\n" - L"This feature allows players who\n" - L"add your friend code to meet up with you,\n" - L"even if you don't add them back."; - - YesNoPopupPage* yesNoPopupPage = - section->page(PageId::YesNoPopup); - yesNoPopupPage->reset(); - yesNoPopupPage->setWindowMessage(0x19CA, &formatParam); - yesNoPopupPage->configureButton( - 0, 0xFAC, nullptr, Animation::None, s_onYesOrNo - ); - yesNoPopupPage->configureButton( - 1, 0xFAD, nullptr, Animation::None, s_onYesOrNo - ); - yesNoPopupPage->setDefaultChoice(1); - - push(PageId::YesNoPopup, Animation::Next); - break; - } - case State::Result: { - FormatParam formatParam{}; - if (!s_sentOpenHostValue) { - formatParam.strings[0] = L"You have lost connection to\n" - L"the server.\n\n" - L"Please try again later."; - } else { - if (s_enableOpenHost) { - formatParam.strings[0] = L"Open Host is now enabled!"; - } else { - formatParam.strings[0] = L"Open Host is now disabled!"; - } - } - - MessagePopupPage* messagePopupPage = - section->page(PageId::MessagePopup); - messagePopupPage->reset(); - messagePopupPage->setWindowMessage(0x19CA, &formatParam); - - push(PageId::MessagePopup, Animation::Next); - break; - } - } - - s_state = state; - } - - void onOption(u32 /* localPlayerId */) - { - transition(State::Prompt); - } - - void onYesOrNo(int choice, void* /* pushButton */) - { - GameSpy::GPConnection* gpConnection = DWC::stpMatchCnt->connection; - if (!gpConnection) { - s_sentOpenHostValue = false; - return; - } - s_sentOpenHostValue = true; - - bool enableOpenHost = choice == 0; - - char openHostValue[2]; - openHostValue[0] = '0' + enableOpenHost; - openHostValue[1] = '\0'; - GameSpy::gpiSendLocalInfo( - gpConnection, "\\wwfc_openhost\\", openHostValue - ); - - s_enableOpenHost = enableOpenHost; - } - /* 0x044 */ u8 _044[0xF34 - 0x044]; - - static State s_state; - static mkw::UI::MenuInputManager::Handler* s_onOption; - static mkw::UI::YesNoPage::Handler* s_onYesOrNo; - static bool s_enableOpenHost; - static bool s_sentOpenHostValue; }; static_assert(sizeof(WifiFriendMenuPage) == 0xF34); diff --git a/payload/wwfcFeature.cpp b/payload/wwfcFeature.cpp index 26dd88a..3d0d89d 100644 --- a/payload/wwfcFeature.cpp +++ b/payload/wwfcFeature.cpp @@ -1,5 +1,6 @@ #include "import/mkw/net/itemHandler.hpp" #include "import/mkw/net/selectHandler.hpp" +#include "import/mkw/ui/page/friendRoomPage.hpp" #include "import/mkw/ui/page/wifiFriendMenuPage.hpp" #include "import/mkw/ui/page/wifiMenuPage.hpp" #include "wwfcPatch.hpp" @@ -10,14 +11,11 @@ namespace mkw::UI #if RMC -WifiFriendMenuPage::State WifiFriendMenuPage::s_state = - WifiFriendMenuPage::State::Previous; -MenuInputManager::Handler* WifiFriendMenuPage::s_onOption = - nullptr; -YesNoPage::Handler* WifiFriendMenuPage::s_onYesOrNo = - nullptr; -bool WifiFriendMenuPage::s_enableOpenHost = false; -bool WifiFriendMenuPage::s_sentOpenHostValue = false; +OpenHostPage::State OpenHostPage::s_state = OpenHostPage::State::Previous; +MenuInputManager::Handler* OpenHostPage::s_onOption = nullptr; +YesNoPage::Handler* OpenHostPage::s_onYesOrNo = nullptr; +bool OpenHostPage::s_enableOpenHost = false; +bool OpenHostPage::s_sentOpenHostValue = false; const wchar_t* WifiMenuPage::s_messageOfTheDay = L"Welcome to\nWiiLink Wi-Fi Connection!"; @@ -149,6 +147,27 @@ WWFC_DEFINE_PATCH = { }; // Allow for the "Open Host" feature to be enabled via the press of a button +WWFC_DEFINE_PATCH = { + Patch::WritePointer( + WWFC_PATCH_LEVEL_FEATURE, + RMCXD_PORT(0x808B9008, 0x808BABF8, 0x808B8158, 0x808A7470), // + FriendRoomPage_onActivate + ), +}; +WWFC_DEFINE_PATCH = { + Patch::WritePointer( + WWFC_PATCH_LEVEL_FEATURE, + RMCXD_PORT(0x808B900C, 0x808BABFC, 0x808B815C, 0x808A7474), // + FriendRoomPage_onDeactivate + ), +}; +WWFC_DEFINE_PATCH = { + Patch::WritePointer( + WWFC_PATCH_LEVEL_FEATURE, + RMCXD_PORT(0x808B902C, 0x808BAC1C, 0x808B817C, 0x808A7494), // + FriendRoomPage_onRefocus + ), +}; WWFC_DEFINE_PATCH = { Patch::WritePointer( WWFC_PATCH_LEVEL_FEATURE,