Skip to content

Commit

Permalink
Prepare for future >2 players support
Browse files Browse the repository at this point in the history
  • Loading branch information
BernardoGomesNegri committed Dec 26, 2024
1 parent d7227f2 commit 754ec47
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 30 deletions.
4 changes: 2 additions & 2 deletions src/libretro/core/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,9 @@ namespace MelonDsDs {
int LanRecvPacket(uint8_t* data) noexcept;

void MpStarted(retro_netpacket_send_t send, retro_netpacket_poll_receive_t poll_receive) noexcept;
void MpPacketReceived(const void *buf, size_t len) noexcept;
void MpPacketReceived(const void *buf, size_t len, uint16_t client_id) noexcept;
void MpStopped() noexcept;
bool MpSendPacket(const Packet &p) const noexcept;
bool MpSendPacket(const Packet &p) noexcept;
std::optional<Packet> MpNextPacket() noexcept;
std::optional<Packet> MpNextPacketBlock() noexcept;
bool MpActive() const noexcept;
Expand Down
16 changes: 8 additions & 8 deletions src/libretro/libretro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ extern "C" void MelonDsDs::MpStarted(uint16_t client_id, retro_netpacket_send_t
}

extern "C" void MelonDsDs::MpReceived(const void* buf, size_t len, uint16_t client_id) noexcept {
MelonDsDs::Core.MpPacketReceived(buf, len);
MelonDsDs::Core.MpPacketReceived(buf, len, client_id);
}

extern "C" void MelonDsDs::MpStopped() noexcept {
Expand All @@ -348,7 +348,7 @@ int DeconstructPacket(u8 *data, u64 *timestamp, const std::optional<MelonDsDs::P
}

int Platform::MP_SendPacket(u8* data, int len, u64 timestamp, void*) {
return MelonDsDs::Core.MpSendPacket(MelonDsDs::Packet(data, len, timestamp, 0, false)) ? len : 0;
return MelonDsDs::Core.MpSendPacket(MelonDsDs::Packet(data, len, timestamp, 0, MelonDsDs::Packet::Type::Other)) ? len : 0;
}

int Platform::MP_RecvPacket(u8* data, u64* timestamp, void*) {
Expand All @@ -357,7 +357,7 @@ int Platform::MP_RecvPacket(u8* data, u64* timestamp, void*) {
}

int Platform::MP_SendCmd(u8* data, int len, u64 timestamp, void*) {
return MelonDsDs::Core.MpSendPacket(MelonDsDs::Packet(data, len, timestamp, 0, false)) ? len : 0;
return MelonDsDs::Core.MpSendPacket(MelonDsDs::Packet(data, len, timestamp, 0, MelonDsDs::Packet::Type::Cmd)) ? len : 0;
}

int Platform::MP_SendReply(u8 *data, int len, u64 timestamp, u16 aid, void*) {
Expand All @@ -369,11 +369,11 @@ int Platform::MP_SendReply(u8 *data, int len, u64 timestamp, u16 aid, void*) {
// [1] https://github.com/melonDS-emu/melonDS/blob/817b409ec893fb0b2b745ee18feced08706419de/src/net/LAN.cpp#L1074
// [2] https://melonds.kuribo64.net/comments.php?id=25
retro_assert(aid < 16);
return MelonDsDs::Core.MpSendPacket(MelonDsDs::Packet(data, len, timestamp, aid, true)) ? len : 0;
return MelonDsDs::Core.MpSendPacket(MelonDsDs::Packet(data, len, timestamp, aid, MelonDsDs::Packet::Type::Reply)) ? len : 0;
}

int Platform::MP_SendAck(u8* data, int len, u64 timestamp, void*) {
return MelonDsDs::Core.MpSendPacket(MelonDsDs::Packet(data, len, timestamp, 0, false)) ? len : 0;
return MelonDsDs::Core.MpSendPacket(MelonDsDs::Packet(data, len, timestamp, 0, MelonDsDs::Packet::Type::Cmd)) ? len : 0;
}

int Platform::MP_RecvHostPacket(u8* data, u64 * timestamp, void*) {
Expand All @@ -387,7 +387,7 @@ u16 Platform::MP_RecvReplies(u8* packets, u64 timestamp, u16 aidmask, void*) {
}
u16 ret = 0;
int loops = 0;
while(ret != aidmask) {
while((ret & aidmask) != aidmask) {
std::optional<MelonDsDs::Packet> o_p = MelonDsDs::Core.MpNextPacketBlock();
if(!o_p.has_value()) {
return ret;
Expand All @@ -396,11 +396,11 @@ u16 Platform::MP_RecvReplies(u8* packets, u64 timestamp, u16 aidmask, void*) {
if(p.Timestamp() < (timestamp - 32)) {
continue;
}
if(!p.IsReply()) {
if(p.PacketType() != MelonDsDs::Packet::Type::Reply) {
continue;
}
ret |= 1<<p.Aid();
memcpy(&packets[(p.Aid()-1)*1024], p.Data(), p.Length());
memcpy(&packets[(p.Aid()-1)*1024], p.Data(), std::min(p.Length(), (uint64_t)1024));
loops++;
}
return ret;
Expand Down
59 changes: 49 additions & 10 deletions src/libretro/net/mp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,31 @@ Packet Packet::parsePk(const void *buf, uint64_t len) {
size_t dataLen = len - HeaderSize;
uint64_t timestamp = swapToNetwork(*(const uint64_t*)(indexableBuf));
uint8_t aid = *(const uint8_t*)(indexableBuf + 8);
uint8_t isReply = *(const uint8_t*)(indexableBuf + 9);
retro_assert(isReply == 1 || isReply == 0);
return Packet(data, dataLen, timestamp, aid, isReply == 1);
uint8_t type = *(const uint8_t*)(indexableBuf + 9);
// type 2 means cmd frame
// type 1 means reply frame
// type 0 means anything else
retro_assert(type == 2 || type == 1 || type == 0);
Packet::Type pkType;
switch (type) {
case 0:
pkType = Other;
break;
case 1:
pkType = Reply;
break;
case 2:
pkType = Cmd;
break;
}
return Packet(data, dataLen, timestamp, aid, pkType);
}

Packet::Packet(const void *data, uint64_t len, uint64_t timestamp, uint8_t aid, bool isReply) :
Packet::Packet(const void *data, uint64_t len, uint64_t timestamp, uint8_t aid, Packet::Type type) :
_data((unsigned char*)data, (unsigned char*)data + len),
_timestamp(timestamp),
_aid(aid),
_isReply(isReply){
_type(type){
}

std::vector<uint8_t> Packet::ToBuf() const {
Expand All @@ -38,7 +53,19 @@ std::vector<uint8_t> Packet::ToBuf() const {
uint64_t netTimestamp = swapToNetwork(_timestamp);
ret.insert(ret.end(), (const char *)&netTimestamp, ((const char *)&netTimestamp) + sizeof(uint64_t));
ret.push_back(_aid);
ret.push_back(_isReply);
uint8_t numericalType = 0;
switch(_type) {
case Other:
numericalType = 0;
break;
case Reply:
numericalType = 1;
break;
case Cmd:
numericalType = 2;
break;
}
ret.push_back(numericalType);
ret.insert(ret.end(), _data.begin(), _data.end());
return ret;
}
Expand All @@ -55,9 +82,14 @@ void MpState::SetPollFn(retro_netpacket_poll_receive_t pollFn) noexcept {
_pollFn = pollFn;
}

void MpState::PacketReceived(const void *buf, size_t len) noexcept {
void MpState::PacketReceived(const void *buf, size_t len, uint16_t client_id) noexcept {
retro_assert(IsReady());
receivedPackets.push(Packet::parsePk(buf, len));
Packet p = Packet::parsePk(buf, len);
if(p.PacketType() == Packet::Type::Cmd) {
_hostId = client_id;
//retro::debug("Host client id is {}", client_id);
}
receivedPackets.push(std::move(p));
}

std::optional<Packet> MpState::NextPacket() noexcept {
Expand Down Expand Up @@ -92,9 +124,16 @@ std::optional<Packet> MpState::NextPacketBlock() noexcept {
return std::nullopt;
}

void MpState::SendPacket(const Packet &p) const noexcept {
void MpState::SendPacket(const Packet &p) noexcept {
retro_assert(IsReady());
_sendFn(RETRO_NETPACKET_UNSEQUENCED | RETRO_NETPACKET_UNRELIABLE | RETRO_NETPACKET_FLUSH_HINT, p.ToBuf().data(), p.Length() + HeaderSize, RETRO_NETPACKET_BROADCAST);
uint16_t dest = RETRO_NETPACKET_BROADCAST;
if(p.PacketType() == Packet::Type::Cmd) {
_hostId = std::nullopt;
}
if(p.PacketType() == Packet::Type::Reply && _hostId.has_value()) {
dest = _hostId.value();
}
_sendFn(RETRO_NETPACKET_UNSEQUENCED | RETRO_NETPACKET_UNRELIABLE | RETRO_NETPACKET_FLUSH_HINT, p.ToBuf().data(), p.Length() + HeaderSize, dest);
}


19 changes: 12 additions & 7 deletions src/libretro/net/mp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,22 @@ constexpr size_t HeaderSize = sizeof(uint64_t) + sizeof(uint8_t) + sizeof(uint8_

class Packet {
public:
enum Type {
Reply, Cmd, Other
};

static Packet parsePk(const void *buf, uint64_t len);
explicit Packet(const void *data, uint64_t len, uint64_t timestamp, uint8_t aid, bool isReply);
explicit Packet(const void *data, uint64_t len, uint64_t timestamp, uint8_t aid, Packet::Type type);

[[nodiscard]] uint64_t Timestamp() const noexcept {
return _timestamp;
};
[[nodiscard]] uint8_t Aid() const noexcept {
return _aid;
};
[[nodiscard]] bool IsReply() const noexcept {
return _isReply;
};
[[nodiscard]] Packet::Type PacketType() const noexcept {
return _type;
}
[[nodiscard]] const void *Data() const noexcept {
return _data.data();
};
Expand All @@ -34,22 +38,23 @@ class Packet {
private:
uint64_t _timestamp;
uint8_t _aid;
bool _isReply;
Packet::Type _type;
std::vector<uint8_t> _data;
};

class MpState {
public:
void PacketReceived(const void *buf, size_t len) noexcept;
void PacketReceived(const void *buf, size_t len, uint16_t client_id) noexcept;
void SetSendFn(retro_netpacket_send_t sendFn) noexcept;
void SetPollFn(retro_netpacket_poll_receive_t pollFn) noexcept;
bool IsReady() const noexcept;
void SendPacket(const Packet &p) const noexcept;
void SendPacket(const Packet &p) noexcept;
std::optional<Packet> NextPacket() noexcept;
std::optional<Packet> NextPacketBlock() noexcept;
private:
retro_netpacket_send_t _sendFn;
retro_netpacket_poll_receive_t _pollFn;
std::optional<uint16_t> _hostId;
std::queue<Packet> receivedPackets;
};
}
6 changes: 3 additions & 3 deletions src/libretro/platform/mp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ void MelonDsDs::CoreState::MpStarted(retro_netpacket_send_t send, retro_netpacke
retro::info("Starting multiplayer on libretro side");
}

void MelonDsDs::CoreState::MpPacketReceived(const void *buf, size_t len) noexcept {
void MelonDsDs::CoreState::MpPacketReceived(const void *buf, size_t len, uint16_t client_id) noexcept {
ZoneScopedN(TracyFunction);
_mpState.PacketReceived(buf, len);
_mpState.PacketReceived(buf, len, client_id);
}

void MelonDsDs::CoreState::MpStopped() noexcept {
Expand All @@ -42,7 +42,7 @@ void MelonDsDs::CoreState::MpStopped() noexcept {
retro::info("Stopping multiplayer on libretro side");
}

bool MelonDsDs::CoreState::MpSendPacket(const MelonDsDs::Packet &p) const noexcept {
bool MelonDsDs::CoreState::MpSendPacket(const MelonDsDs::Packet &p) noexcept {
ZoneScopedN(TracyFunction);
if(!_mpState.IsReady()) {
return false;
Expand Down

0 comments on commit 754ec47

Please sign in to comment.