Skip to content

Commit

Permalink
[MKW] Fix a bug that leads to the rejection of one's item request wit…
Browse files Browse the repository at this point in the history
…hout justification

The root cause of the bug is that the game utilizes the time at which a player receives an item as an identifier when responding to a client's request for an item. The aforementioned value is not unique.
  • Loading branch information
MikeIsAStar committed Feb 21, 2024
1 parent 4a8f3d1 commit aee7ed4
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 64 deletions.
19 changes: 16 additions & 3 deletions payload/import/mkw/net/itemHandler.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include <wwfcUtil.h>
#include "import/mkw/item.hpp"

namespace mkw::Net
{
Expand Down Expand Up @@ -98,7 +98,7 @@ class ItemHandler
}
}

/* 0x00 */ u8 _00;
/* 0x00 */ u8 receivedTime;
/* 0x01 */ u8 heldItem;
/* 0x02 */ u8 trailedItem;
/* 0x03 */ HeldPhase heldPhase;
Expand All @@ -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));
Expand Down
55 changes: 48 additions & 7 deletions payload/import/mkw/net/net.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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];
}
Expand All @@ -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) {
Expand Down Expand Up @@ -113,7 +128,7 @@ class RKNetController
}
}

bool inVanillaRaceScene()
bool inVanillaRaceScene() const
{
using namespace mkw::System;

Expand All @@ -125,7 +140,7 @@ class RKNetController
return inVanillaMatch();
}

static RKNetController* Instance()
static NetController* Instance()
{
return s_instance;
}
Expand All @@ -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

Expand Down
36 changes: 36 additions & 0 deletions payload/import/mkw/system/raceManager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#pragma once

#include <wwfcUtil.h>

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
4 changes: 2 additions & 2 deletions payload/wwfcBugFix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
105 changes: 68 additions & 37 deletions payload/wwfcFeature.cpp
Original file line number Diff line number Diff line change
@@ -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 <cstring>
Expand All @@ -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
Expand Down Expand Up @@ -131,7 +98,6 @@ ShowMessageOfTheDay(mkw::UI::WifiMenuPage* wifiMenuPage)
}

wifiMenuPage->showMessageOfTheDay();

WifiMenuPage::SeenMessageOfTheDay();
}
}
Expand All @@ -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<u8>(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
Loading

0 comments on commit aee7ed4

Please sign in to comment.