Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions payload/game/net/MiscPacketHandler.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include <Common.S>

PATCH_REPLACE_START(MiscPacketHandler_updateAsRacer, 0x4c)
// Original instruction sets RaceManager::m_canCountdownStart to true
// Nopped since mkw-server now handles this. Ideally, we'd rewrite in C++,
// but this function is complex and difficult to functionally match.
nop
PATCH_REPLACE_END(MiscPacketHandler_updateAsRacer, 0x4c)
42 changes: 41 additions & 1 deletion payload/game/net/MiscPacketHandler.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,43 @@
#include "MiscPacketHandler.hh"

namespace Net {} // namespace Net
#include <sp/net/mkw_server/MKWServer.hh>

namespace Net {

void MiscPacketHandler::setAckReady() {
m_readyAcked = true;
}

void MiscPacketHandler::init() {
REPLACED(init)();

m_timeUntilReady = 240;
m_readyAcked = false;
}

void MiscPacketHandler::updateReadyTimer() {
if (m_timeUntilReady > 0) {
m_timeUntilReady--;
} else {
MKWServer::sendReadyPacket();
// Until we get an ack, try to send again in 5 frames.
m_timeUntilReady = 5;
}
}

void MiscPacketHandler::updateAsRacer() {
if (!m_readyAcked) {
updateReadyTimer();
}

REPLACED(updateAsRacer)();
}

} // namespace Net

void MiscPacketHandler_setAckReady() {
// Need to check for nullptr in case if an ack is unexpectedly sent outside of race scene.
if (auto *miscPacketHandler = Net::MiscPacketHandler::Instance()) {
miscPacketHandler->setAckReady();
}
}
4 changes: 4 additions & 0 deletions payload/game/net/MiscPacketHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#pragma once

// Defined here to expose to C code.
void MiscPacketHandler_setAckReady();
39 changes: 33 additions & 6 deletions payload/game/net/MiscPacketHandler.hh
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
#include <Common.hh>

#include "game/net/records/Event.hh"
#include "game/net/records/RH1.hh"
#include "game/net/records/RH2.hh"
#include "game/net/records/RaceData.hh"
#include "game/net/records/Select.hh"

extern "C" {
#include <revolution/os.h>
Expand All @@ -16,16 +13,36 @@ namespace Net {

// MiscPacketHandler runs exclusively in race scene. It handles everything netcode during a race.
class MiscPacketHandler {
public:
// Added. sets m_readyAcked
void setAckReady();

static MiscPacketHandler *Instance() {
return s_instance;
}

private:
// 0x806532d8
// Called exactly once at the start of a race to initialize members.
// Hooked to initialize mkw-server members.
REPLACE void init();
void REPLACED(init)();

// 0x80653728
// The main loop. Runs when m_isPrepared is true. This runs in online races
// but also rival ghost races to update friend status
void update();

// Added.
// Updates m_timeUntilReady. Calls MKWServer::sendReadyPacket() when m_timeUntilReady is 0.
void updateReadyTimer();

// 0x80654150
// Runs only when racing. Synchronizes race start, imports, exports, and processes records
// specifically as a racer.
void updateAsRacer();
// Hooked to handle mkw-server client synchronization.
REPLACE void updateAsRacer();
void REPLACED(updateAsRacer)();

// 0x80654d08
// Exports relevant records as a racer (as opposed to a spectator)
Expand Down Expand Up @@ -55,8 +72,14 @@ private:
// Schecules a disconnect. Set if we're out of sync with other players.
bool m_scheduleDisconnect;

// Padding
u8 _002[0x004 - 0x002];
// Added, was padding. Time (in frames) until we're ready to start the countdown.
// This is initialized to 240 frames (4 seconds) at the start of each race to account
// for the intro camera pan, and decremented each frame. When the timer is 0, send
// a ready packet to mkw-server.
u8 m_timeUntilReady;

// Added, was padding. Set when mkw-server has acked our ready packet.
bool m_readyAcked;

// Bitfield set by RH1.raceSeed
u32 m_aidsLoadedIntoRace;
Expand Down Expand Up @@ -94,3 +117,7 @@ private:
static_assert(sizeof(MiscPacketHandler) == 0x1c8);

} // namespace Net

// Exposed to C b/c UDP packets are handled in a C function (DWCi_GT2UnrecognizedMessageCallback).
// TODO: Rewrite in C++.
extern "C" void MiscPacketHandler_setAckReady();
6 changes: 6 additions & 0 deletions payload/game/system/RaceManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,9 @@ void RaceManager::Player::calc() {
}

} // namespace System

void RaceManager_startCountdown() {
if (auto *raceManager = System::RaceManager::Instance()) {
raceManager->startCountdown();
}
}
4 changes: 4 additions & 0 deletions payload/game/system/RaceManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#pragma once

// Defined here to expose to C code.
void RaceManager_startCountdown();
9 changes: 9 additions & 0 deletions payload/game/system/RaceManager.hh
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ public:
return m_countdownTimer;
}

void startCountdown() {
m_canCountdownStart = true;
}

static RaceManager *Instance() {
return s_instance;
}
Expand Down Expand Up @@ -78,3 +82,8 @@ private:
static_assert(sizeof(RaceManager) == 0x4c);

} // namespace System

// Exposed to C b/c UDP packets are handled in a C function (DWCi_GT2UnrecognizedMessageCallback).
// And we need to be able to start the countdown from UDP packet handling.
// TODO: Rewrite in C++.
extern "C" void RaceManager_startCountdown();
39 changes: 39 additions & 0 deletions payload/revolution/dwc/DWCTransport.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
#include "DWCTransport.h"

#include <game/net/MiscPacketHandler.h>
#include <game/system/RaceManager.h>

#include <sp/net/mkw_server/MKWServer.h>

#include <string.h>

#define START_MESSAGE "ST"
#define PING_MESSAGE "PI"
#define READY_ACK_MESSAGE "RA"

bool isReadyAckPacket(const u8 *message, s32 len) {
return len == 2 &&
strncmp((const char *)message, READY_ACK_MESSAGE, strlen(READY_ACK_MESSAGE)) == 0;
}

bool isStartPacket(const u8 *message, s32 len) {
return len == 2 && strncmp((const char *)message, START_MESSAGE, strlen(START_MESSAGE)) == 0;
}

bool isPingPacket(const u8 *message, s32 len) {
return len == 2 && strncmp((const char *)message, PING_MESSAGE, strlen(PING_MESSAGE)) == 0;
}

BOOL DWCi_GT2UnrecognizedMessageCallback(GT2Socket socket, u32 ip, u16 port, const u8 *message,
s32 len) {
if (message == NULL || len == 0) {
Expand All @@ -14,6 +36,23 @@ BOOL DWCi_GT2UnrecognizedMessageCallback(GT2Socket socket, u32 ip, u16 port, con
return GT2True;
}

if (isReadyAckPacket(message, len)) {
SP_LOG("Received ready ACK packet from mkw-server!");
MiscPacketHandler_setAckReady();
return GT2True;
}

if (isStartPacket(message, len)) {
SP_LOG("Received Start packet from mkw-server!");
RaceManager_startCountdown();
return GT2True;
}

if (isPingPacket(message, len)) {
sendPong();
return GT2True;
}

MKWServerPacketType messageType = message[0];
switch (messageType) {
case MKW_SERVER_RACE_PACKET:
Expand Down
30 changes: 29 additions & 1 deletion payload/sp/net/mkw_server/MKWServer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,28 @@ bool hasMKWServerAddress() {
return s_mkwServerAddr.addr.addr != 0 && s_mkwServerAddr.port != 0;
}

void sendReadyPacket() {
if (!hasMKWServerAddress()) {
SP_LOG("sendReady() can't send: Don't have mkw-server address!");
return;
}

u8 msg[2] = {0x52, 0x45}; // RE

bool result = SOSendTo(s_dwcMatch->qrec->hbsock, &msg, sizeof(msg), 0, &s_mkwServerAddr);
if (!result) {
SP_LOG("Failed to send Race packet to mkw-server! SOSendTo failed!");
}
}

bool trySendRacePacketToMKWServer(const void *data, u32 size) {
if (!hasMKWServerAddress()) {
return false;
}

bool result = SOSendTo(s_dwcMatch->qrec->hbsock, data, size, 0, &s_mkwServerAddr);
if (!result) {
SP_LOG("Failed to send to MKW Server!");
SP_LOG("Failed to send Race packet to mkw-server!");
}
return result;
}
Expand Down Expand Up @@ -94,6 +108,20 @@ bool handleSearchIdPacket(const u8 *packet, u32 size) {
return true;
}

void sendPong() {
if (!hasMKWServerAddress()) {
SP_LOG("sendPong() can't send: Don't have mkw-server address!");
return;
}

u8 msg[2] = {0x50, 0x4F}; // PO

bool result = SOSendTo(s_dwcMatch->qrec->hbsock, &msg, sizeof(msg), 0, &s_mkwServerAddr);
if (!result) {
SP_LOG("Failed to send Pong packet to mkw-server! SOSendTo failed!");
}
}

bool sendMessageToQR2(const u8 *data, u32 size) {
SOSockAddrIn qr2Addr;
qr2Addr.len = sizeof(SOSockAddrIn);
Expand Down
4 changes: 3 additions & 1 deletion payload/sp/net/mkw_server/MKWServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@

EXTERN_C bool verifySearchIdMagic(const u8 *packet, u32 size);

EXTERN_C bool handleSearchIdPacket(const u8 *packet, u32 size);
EXTERN_C bool handleSearchIdPacket(const u8 *packet, u32 size);

EXTERN_C void sendPong();
4 changes: 4 additions & 0 deletions payload/sp/net/mkw_server/MKWServer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ u64 getSearchId();

bool hasMKWServerAddress();

void sendReadyPacket();

EXTERN_C bool trySendRacePacketToMKWServer(const void *data, u32 size);

EXTERN_C bool verifySearchIdMagic(const u8 *packet, u32 size);

EXTERN_C bool handleSearchIdPacket(const u8 *packet, u32 size);

EXTERN_C void sendPong();

bool sendMessageToQR2(const u8 *data, u32 size);
} // namespace MKWServer
3 changes: 3 additions & 0 deletions port.py
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ def port(self, address):
Chunk(0x809c1988, 0x809c198c, 0x809bd378),
Chunk(0x809c19a0, 0x809c19bc, 0x809bd180),
Chunk(0x809c1e38, 0x809c1e3c, 0x809bd508),
Chunk(0x809c1f50, 0x809c1f54, 0x809bd790),
Chunk(0x809c20e0, 0x809c20e4, 0x809bd920),
Chunk(0x809c2108, 0x809c210c, 0x809bd958),
Chunk(0x809c2118, 0x809c211c, 0x809bd940),
Expand Down Expand Up @@ -536,6 +537,7 @@ def port(self, address):
Chunk(0x809c18f8, 0x809c18fc, 0x809c0958),
Chunk(0x809c1988, 0x809c198c, 0x809c09e8),
Chunk(0x809c19a0, 0x809c19bc, 0x809c0a00),
Chunk(0x809c1f50, 0x809c1f54, 0x809c0fb0),
Chunk(0x809c20e0, 0x809c20e4, 0x809c1140),
Chunk(0x809c2108, 0x809c210c, 0x809c1168),
Chunk(0x809c2118, 0x809c211c, 0x809c1178),
Expand Down Expand Up @@ -635,6 +637,7 @@ def port(self, address):
Chunk(0x809c1988, 0x809c198c, 0x809affc8),
Chunk(0x809c19a0, 0x809c19bc, 0x809affe0),
Chunk(0x809c1e38, 0x809c1e3c, 0x809b0478),
Chunk(0x809c1f50, 0x809c1f54, 0x809b0590),
Chunk(0x809c20e0, 0x809c20e4, 0x809b0720),
Chunk(0x809c2108, 0x809c210c, 0x809b0748),
Chunk(0x809c2118, 0x809c211c, 0x809b0758),
Expand Down
3 changes: 3 additions & 0 deletions symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,9 @@
0x8063e924 _ZN2UI24LayoutUIControlScaleFade5vf_28Ev
0x80643168 onInit
0x80649590 DCPageCalc
0x806532d8 _ZN3Net17MiscPacketHandler4initEv
0x80654038 _ZNK3Net17MiscPacketHandler16isEveryoneInRaceEv
0x80654150 MiscPacketHandler_updateAsRacer
0x80654150 _ZN3Net17MiscPacketHandler13updateAsRacerEv
0x806554a0 _ZN3Net17MiscPacketHandler21processRecvRH1RecordsEv
0x806554a0 MiscPacketHandler_handleLaggings
Expand Down Expand Up @@ -588,6 +590,7 @@
0x809bd740 _ZN6System9RootScene10s_instanceE
0x809c18f8 _ZN4Kart17KartObjectManager10s_instanceE
0x809c1e38 _ZN2UI14SectionManager10s_instanceE
0x809c1f50 _ZN3Net17MiscPacketHandler10s_instanceE
0x809c20d8 _ZN3Net10NetManager10s_instanceE
0x809c20e0 _ZN3Net11RoomHandler10s_instanceE
0x809c2100 _ZN3Net13SelectHandler10s_instanceE
Expand Down
Loading