diff --git a/payload/import/mkw/net/itemHandler.hpp b/payload/import/mkw/net/itemHandler.hpp index 214b9a4..9dab179 100644 --- a/payload/import/mkw/net/itemHandler.hpp +++ b/payload/import/mkw/net/itemHandler.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include "import/mkw/item.hpp" namespace mkw::Net { @@ -98,7 +98,7 @@ class ItemHandler } } - /* 0x00 */ u8 _00; + /* 0x00 */ u8 receivedTime; /* 0x01 */ u8 heldItem; /* 0x02 */ u8 trailedItem; /* 0x03 */ HeldPhase heldPhase; @@ -108,13 +108,26 @@ class ItemHandler static_assert(sizeof(Packet) == 0x08); + Packet& sendPacket(u32 localPlayerIndex) + { + return m_sendPacket[localPlayerIndex]; + } + + void setReceivedTime(u32 receivedTime, u32 playerIndex) + { + m_receivedTime[playerIndex] = receivedTime; + } + static ItemHandler* Instance() { return s_instance; } private: - /* 0x000 */ u8 _000[0x184 - 0x000]; + /* 0x000 */ Packet m_sendPacket[2]; + /* 0x010 */ u8 _010[0x0A0 - 0x010]; + /* 0x0A0 */ u32 m_receivedTime[12]; + /* 0x0D0 */ u8 _0D0[0x184 - 0x0D0]; static ItemHandler* s_instance AT(RMCXD_PORT(0x809C20F8, 0x809BD950, 0x809C1158, 0x809B0738)); diff --git a/payload/import/mkw/net/net.hpp b/payload/import/mkw/net/net.hpp index d0c5e3f..58e7a18 100644 --- a/payload/import/mkw/net/net.hpp +++ b/payload/import/mkw/net/net.hpp @@ -28,7 +28,7 @@ struct __attribute__((packed)) RacePacket { static_assert(sizeof(RacePacket) == 0x10); // https://github.com/SeekyCt/mkw-structures/blob/master/rknetcontroller.h -class RKNetController +class NetController { public: enum JoinType { @@ -58,14 +58,14 @@ class RKNetController processRacePacket(u32 playerAid, RacePacket* racePacket, u32 packetSize) { LONGCALL void processRacePacket( - RKNetController * rkNetController, u32 playerAid, + NetController * netController, u32 playerAid, RacePacket * racePacket, u32 packetSize ) AT(RMCXD_PORT(0x80659A84, 0x806555FC, 0x806590F0, 0x80647D9C)); processRacePacket(this, playerAid, racePacket, packetSize); } - ConnectionInfo& currentConnectionInfo() + const ConnectionInfo& currentConnectionInfo() const { return m_connectionInfo[m_currentConnectionInfoIndex]; } @@ -75,6 +75,21 @@ class RKNetController return m_joinType; } + u8 myAid() const + { + return currentConnectionInfo().myAid; + } + + bool isAidTheServer(u8 playerAid) const + { + return playerAid == currentConnectionInfo().serverAid; + } + + bool amITheServer() const + { + return isAidTheServer(myAid()); + } + bool inVanillaMatch() const { switch (m_joinType) { @@ -113,7 +128,7 @@ class RKNetController } } - bool inVanillaRaceScene() + bool inVanillaRaceScene() const { using namespace mkw::System; @@ -125,7 +140,7 @@ class RKNetController return inVanillaMatch(); } - static RKNetController* Instance() + static NetController* Instance() { return s_instance; } @@ -138,11 +153,37 @@ class RKNetController /* 0x291C */ int m_currentConnectionInfoIndex; /* 0x2920 */ u8 _2920[0x29C8 - 0x2920]; - static RKNetController* s_instance + static NetController* s_instance AT(RMCXD_PORT(0x809C20D8, 0x809BD918, 0x809C1138, 0x809B0718)); }; -static_assert(sizeof(RKNetController) == 0x29C8); +static_assert(sizeof(NetController) == 0x29C8); + +class RacePacketHandler +{ +public: + u32 playerIdToLocalPlayerIndex(u32 playerId) + { + LONGCALL u32 playerIdToLocalPlayerIndex( + RacePacketHandler * racePacketHandler, u32 playerId + ) AT(RMCXD_PORT(0x80654918, 0x80650490, 0x80653F84, 0x80642C30)); + + return playerIdToLocalPlayerIndex(this, playerId); + } + + static RacePacketHandler* Instance() + { + return s_instance; + } + +private: + /* 0x000 */ u8 _000[0x1C8 - 0x000]; + + static RacePacketHandler* s_instance + AT(RMCXD_PORT(0x809C1F50, 0x809BD790, 0x809C0FB0, 0x809B0590)); +}; + +static_assert(sizeof(RacePacketHandler) == 0x1C8); #endif diff --git a/payload/import/mkw/system/raceManager.hpp b/payload/import/mkw/system/raceManager.hpp new file mode 100644 index 0000000..86bdfc8 --- /dev/null +++ b/payload/import/mkw/system/raceManager.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include + +namespace mkw::System +{ + +#if RMC + +class RaceManager +{ +public: + u32 timer() const + { + return m_timer; + } + + static RaceManager* Instance() + { + return s_instance; + } + +private: + /* 0x00 */ u8 _00[0x20 - 0x00]; + /* 0x20 */ u32 m_timer; + /* 0x24 */ u8 _24[0x4C - 0x24]; + + static RaceManager* s_instance + AT(RMCXD_PORT(0x809BD730, 0x809B8F70, 0x809BC790, 0x809ABD70)); +}; + +static_assert(sizeof(RaceManager) == 0x4C); + +#endif + +} // namespace mkw::System diff --git a/payload/wwfcBugFix.cpp b/payload/wwfcBugFix.cpp index 1c08d75..d0db233 100644 --- a/payload/wwfcBugFix.cpp +++ b/payload/wwfcBugFix.cpp @@ -71,8 +71,8 @@ u64 IsUltraShortcutCheckEnabled(u32 r3Discard, u32 r4Save) auto raceConfig = mkw::System::RaceConfig::Instance(); if (raceConfig->raceScenario().isOnlineVersusRace()) { // Check if Worldwide or other vanilla match - auto rkNetController = mkw::Net::RKNetController::Instance(); - if (rkNetController != nullptr && rkNetController->inVanillaMatch()) { + auto netController = mkw::Net::NetController::Instance(); + if (netController && netController->inVanillaMatch()) { enabled = true; } } diff --git a/payload/wwfcFeature.cpp b/payload/wwfcFeature.cpp index c2a4fe3..6110fc4 100644 --- a/payload/wwfcFeature.cpp +++ b/payload/wwfcFeature.cpp @@ -1,6 +1,9 @@ #include "import/dwc.h" #include "import/gamespy.h" +#include "import/mkw/net/itemHandler.hpp" +#include "import/mkw/net/net.hpp" #include "import/mkw/net/selectHandler.hpp" +#include "import/mkw/system/raceManager.hpp" #include "import/mkw/ui/page.hpp" #include "import/mkw/util.hpp" #include @@ -24,42 +27,6 @@ namespace wwfc::Feature #if RMC -static void DecideEngineClass( - mkw::Net::SelectHandler* selectHandler, mkw::Util::Random* random -) -{ - using namespace mkw::Net; - - SelectHandler::Packet& sendPacket = selectHandler->sendPacket(); - - if (random->nextInt(100) < 65) { - sendPacket.engineClass = SelectHandler::Packet::EngineClass::e150cc; - } else { - sendPacket.engineClass = - SelectHandler::Packet::EngineClass::eMirrorMode; - } -} - -// Remove the 100cc engine class from vanilla matches -WWFC_DEFINE_PATCH = { - Patch::CallWithCTR( // - WWFC_PATCH_LEVEL_PARITY, // - RMCXD_PORT(0x806613F8, 0x806594BC, 0x80660A64, 0x8064F710), // - [](mkw::Util::Random* random) -> void { - using namespace mkw::Net; - - SelectHandler* selectHandler = SelectHandler::Instance(); - if (RKNetController::Instance()->inVanillaMatch()) { - DecideEngineClass(selectHandler, random); - } else { - selectHandler->decideEngineClass(); - } - - random->dt(random, -1); - } - ), -}; - extern "C" { __attribute__((__used__)) static GameSpy::GPResult @@ -131,7 +98,6 @@ ShowMessageOfTheDay(mkw::UI::WifiMenuPage* wifiMenuPage) } wifiMenuPage->showMessageOfTheDay(); - WifiMenuPage::SeenMessageOfTheDay(); } } @@ -156,6 +122,71 @@ WWFC_DEFINE_PATCH = { ), }; +// Fix a bug that leads to the rejection of one's item request without +// justification +WWFC_DEFINE_PATCH = { + Patch::BranchWithCTR( // + WWFC_PATCH_LEVEL_BUGFIX | WWFC_PATCH_LEVEL_PARITY, // + RMCXD_PORT(0x8065C6C0, 0x8065D348, 0x8065BD2C, 0x8064A9D8), // + // clang-format off + [](mkw::Net::ItemHandler* itemHandler, u32 playerId, + mkw::Item::ItemBox item) -> void { + using namespace mkw::Net; + using namespace mkw::System; + + u32 localPlayerIndex = + RacePacketHandler::Instance()->playerIdToLocalPlayerIndex(playerId); + ItemHandler::Packet& sendPacket = itemHandler->sendPacket(localPlayerIndex); + u32 timer = RaceManager::Instance()->timer(); + u8 myAid = NetController::Instance()->myAid(); + + sendPacket.receivedTime = (myAid << 1) + localPlayerIndex; + sendPacket.heldItem = static_cast(item); + sendPacket.heldPhase = ItemHandler::Packet::HeldPhase::Decided; + itemHandler->setReceivedTime(timer & 0xFFFFFFF8, playerId); + } + // clang-format on + ), +}; + +static void DecideEngineClass( + mkw::Net::SelectHandler* selectHandler, mkw::Util::Random* random +) +{ + using namespace mkw::Net; + + SelectHandler::Packet& sendPacket = selectHandler->sendPacket(); + + if (random->nextInt(100) < 65) { + sendPacket.engineClass = SelectHandler::Packet::EngineClass::e150cc; + } else { + sendPacket.engineClass = + SelectHandler::Packet::EngineClass::eMirrorMode; + } +} + +// Remove the 100cc engine class from vanilla matches +WWFC_DEFINE_PATCH = { + Patch::CallWithCTR( // + WWFC_PATCH_LEVEL_PARITY, // + RMCXD_PORT(0x806613F8, 0x806594BC, 0x80660A64, 0x8064F710), // + // clang-format off + [](mkw::Util::Random* random) -> void { + using namespace mkw::Net; + + SelectHandler* selectHandler = SelectHandler::Instance(); + if (NetController::Instance()->inVanillaMatch()) { + DecideEngineClass(selectHandler, random); + } else { + selectHandler->decideEngineClass(); + } + + random->dt(random, -1); + } + // clang-format on + ), +}; + #endif } // namespace wwfc::Feature diff --git a/payload/wwfcSecurity.cpp b/payload/wwfcSecurity.cpp index 6963b46..40db203 100644 --- a/payload/wwfcSecurity.cpp +++ b/payload/wwfcSecurity.cpp @@ -149,7 +149,7 @@ static bool IsPacketSizeValid(RacePacket::EType packetType, u8 packetSize) } size_t* packetBufferSizesPointer; - if (!RKNetController::Instance()->inVanillaMatch()) { + if (!NetController::Instance()->inVanillaMatch()) { extern size_t packetBufferSizes[sizeof(RacePacket::sizes)] AT( RMCXD_PORT(0x8089A194, 0x80895AC4, 0x808992F4, 0x808885CC) ); @@ -253,7 +253,7 @@ static bool IsMatchHeaderPacketDataValid( const MatchHeaderHandler::Packet* matchHeaderPacket = reinterpret_cast(packet); - if (!RKNetController::Instance()->inVanillaRaceScene()) { + if (!NetController::Instance()->inVanillaRaceScene()) { return true; } @@ -321,19 +321,22 @@ IsRoomSelectPacketDataValid(const void* packet, u8 packetSize, u8 playerAid) const RoomHandler::Packet* roomPacket = reinterpret_cast(packet); - if (roomPacket->event == RoomHandler::Packet::Event::StartRoom) { - RKNetController::ConnectionInfo& connectionInfo = - RKNetController::Instance()->currentConnectionInfo(); - + switch (roomPacket->event) { + case RoomHandler::Packet::Event::StartRoom: { // Ensure that guests can't start rooms - if (playerAid != connectionInfo.serverAid) { + if (!NetController::Instance()->isAidTheServer(playerAid)) { return false; } + break; + } + default: { + break; + } } } // 'Select' packet else { - if (!RKNetController::Instance()->inVanillaMatch()) { + if (!NetController::Instance()->inVanillaMatch()) { return true; } @@ -435,7 +438,7 @@ IsItemPacketDataValid(const void* packet, u8 packetSize, u8 /* playerAid */) using namespace mkw::Item; using namespace mkw::System; - if (!RKNetController::Instance()->inVanillaRaceScene()) { + if (!NetController::Instance()->inVanillaRaceScene()) { return true; } // Ensure that the table which controls the behaviour of items is loaded @@ -523,7 +526,7 @@ static bool IsEventPacketDataValid( return false; } - if (!RKNetController::Instance()->inVanillaMatch()) { + if (!NetController::Instance()->inVanillaMatch()) { return true; } @@ -597,7 +600,7 @@ static bool IsRacePacketValid( WWFC_DEFINE_PATCH = {Patch::BranchWithCTR( // WWFC_PATCH_LEVEL_CRITICAL, // RMCXD_PORT(0x80658604, 0x8065417C, 0x80657C70, 0x8064691C), // - [](RKNetController* rkNetController, RacePacket* racePacket, u32 packetSize, + [](NetController* netController, RacePacket* racePacket, u32 packetSize, u32 _, u8 playerAid) -> void { if (packetSize >= sizeof(RacePacket)) { LONGCALL u32 NETCalcCRC32( // @@ -632,16 +635,14 @@ WWFC_DEFINE_PATCH = {Patch::BranchWithCTR( // ); } - RKNetController::ConnectionInfo& connectionInfo = - RKNetController::Instance()->currentConnectionInfo(); - if (connectionInfo.myAid == connectionInfo.serverAid) { + if (netController->amITheServer()) { DWC_CloseConnectionHard(playerAid); } return; } - rkNetController->processRacePacket(playerAid, racePacket, packetSize); + netController->processRacePacket(playerAid, racePacket, packetSize); } )};