diff --git a/README.md b/README.md index 8dfd980..853e11b 100644 --- a/README.md +++ b/README.md @@ -174,4 +174,4 @@ Name | Return type | Description ⚠️ packet loss can occur, so always send the full game state or implement retransmission on top of this! -⚠️ the adapter can transfer a maximum of twenty 32-bit words at a time, and messages are often concatenated together, so keep things way below this limit (specially when `forwarding` is on)! \ No newline at end of file +⚠️ the adapter can transfer a maximum of twenty 32-bit words at a time, and messages are often concatenated together, so keep things way below this limit (specially when the protocol is `FORWARD` or `RETRANSMIT`)! \ No newline at end of file diff --git a/lib/LinkWireless.h b/lib/LinkWireless.h index 2b3c2f9..65b2fea 100644 --- a/lib/LinkWireless.h +++ b/lib/LinkWireless.h @@ -39,7 +39,7 @@ // retransmission on top of this! // - the adapter can transfer a maximum of twenty 32-bit words at a // time, and messages are often concatenated together, so keep things way below -// this limit (specially when forwarding is on)! +// this limit (specially when the protocol is FORWARD or RETRANSMIT)! // -------------------------------------------------------------------------- #include @@ -87,16 +87,20 @@ const u16 LINK_WIRELESS_LOGIN_PARTS[] = {0x494e, 0x494e, 0x544e, 0x544e, 0x4e45, class LinkWireless { public: enum State { NEEDS_RESET, AUTHENTICATED, SERVING, CONNECTING, CONNECTED }; + enum Protocol { BASIC, FORWARD, RETRANSMIT }; struct Message { u8 playerId = 0; std::vector data = std::vector{}; + + u32 _packetId = 0; }; explicit LinkWireless(u32 msgTimeout = LINK_WIRELESS_DEFAULT_MSG_TIMEOUT, - bool forwarding = true) { + Protocol protocol = RETRANSMIT) { + // TODO: UPDATE README, TALK ABOUT `protocol` this->msgTimeout = msgTimeout; - this->forwarding = forwarding; + this->protocol = protocol; } bool isActive() { return isEnabled; } @@ -249,9 +253,12 @@ class LinkWireless { Message message; message.playerId = _author < 0 ? playerId : _author; message.data = data; + message._packetId = lastPacketId; outgoingMessages.push_back(message); + lastPacketId++; + return true; } @@ -273,12 +280,14 @@ class LinkWireless { messages = std::vector{}; for (u32 i = 0; i < words.size(); i++) { - u32 header = words[i]; + MessageHeaderSerializer messageHeaderSerializer; - u16 subHeader = msB32(header); - u8 playerCount = msB16(subHeader); - u8 playerId = lsB16(subHeader); - u8 size = (u8)lsB32(header); + messageHeaderSerializer.headerInt = words[i]; + auto header = messageHeaderSerializer.headerStruct; + + u8 playerCount = header.clientCount + 1; + u8 playerId = header.playerId; + u8 size = header.size; if (i + size >= words.size()) { reset(); @@ -312,7 +321,7 @@ class LinkWireless { return disconnect(); } - if (state == SERVING && forwarding) { + if (state == SERVING && (protocol == FORWARD || protocol == RETRANSMIT)) { for (auto& message : messages) send(message.data, message.playerId); } @@ -357,14 +366,28 @@ class LinkWireless { std::vector responses = std::vector{}; }; + struct MessageHeader { + unsigned int packetId : 21; + unsigned int size : 5; + unsigned int playerId : 4; + unsigned int clientCount : 2; + }; + + union MessageHeaderSerializer { + MessageHeader headerStruct; + u32 headerInt; + }; + u32 msgTimeout; - bool forwarding; + Protocol protocol; LinkSPI* linkSPI = new LinkSPI(); LinkGPIO* linkGPIO = new LinkGPIO(); State state = NEEDS_RESET; u8 playerId = 0; u8 playerCount = 1; std::vector outgoingMessages; + u32 lastPacketId = 0; + u32 lastConfirmedPacketId[LINK_WIRELESS_MAX_PLAYERS]; u32 timeouts[LINK_WIRELESS_MAX_PLAYERS]; bool isEnabled = false; @@ -377,9 +400,16 @@ class LinkWireless { std::vector words; for (auto& message : outgoingMessages) { - u32 header = buildU32(buildU16(playerCount, message.playerId), - message.data.size()); - words.push_back(header); + MessageHeader header; + MessageHeaderSerializer messageHeaderSerializer; + + header.clientCount = playerCount - 1; + header.playerId = message.playerId; + header.size = message.data.size(); + header.packetId = message._packetId; + messageHeaderSerializer.headerStruct = header; + + words.push_back(messageHeaderSerializer.headerInt); words.insert(words.end(), message.data.begin(), message.data.end()); } @@ -435,8 +465,11 @@ class LinkWireless { this->playerId = 0; this->playerCount = 1; this->outgoingMessages = std::vector{}; - for (u32 i = 0; i < LINK_WIRELESS_MAX_PLAYERS; i++) + this->lastPacketId = 0; + for (u32 i = 0; i < LINK_WIRELESS_MAX_PLAYERS; i++) { + lastConfirmedPacketId[i] = 0; timeouts[i] = 0; + } stop(); return start();