From c3a79984d8b7422c81514fd7878323f4ba730d9c Mon Sep 17 00:00:00 2001 From: Rodrigo Alfonso Date: Thu, 4 Jan 2024 01:00:48 -0300 Subject: [PATCH 01/10] Enforcing max player restrictions --- lib/LinkUniversal.hpp | 6 ++++-- lib/LinkWireless.hpp | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/LinkUniversal.hpp b/lib/LinkUniversal.hpp index 756e87f..146a426 100644 --- a/lib/LinkUniversal.hpp +++ b/lib/LinkUniversal.hpp @@ -40,6 +40,7 @@ #include #include +#include #include "LinkCable.hpp" #include "LinkWireless.hpp" @@ -101,7 +102,7 @@ class LinkUniversal { LINK_CABLE_DEFAULT_REMOTE_TIMEOUT, LINK_CABLE_DEFAULT_INTERVAL, LINK_CABLE_DEFAULT_SEND_TIMER_ID}, WirelessOptions wirelessOptions = WirelessOptions{ - true, LINK_WIRELESS_MAX_PLAYERS, LINK_WIRELESS_DEFAULT_TIMEOUT, + true, LINK_UNIVERSAL_MAX_PLAYERS, LINK_WIRELESS_DEFAULT_TIMEOUT, LINK_WIRELESS_DEFAULT_REMOTE_TIMEOUT, LINK_WIRELESS_DEFAULT_INTERVAL, LINK_WIRELESS_DEFAULT_SEND_TIMER_ID, LINK_WIRELESS_DEFAULT_ASYNC_ACK_TIMER_ID}) { @@ -109,7 +110,8 @@ class LinkUniversal { cableOptions.baudRate, cableOptions.timeout, cableOptions.remoteTimeout, cableOptions.interval, cableOptions.sendTimerId); this->linkWireless = new LinkWireless( - wirelessOptions.retransmission, true, wirelessOptions.maxPlayers, + wirelessOptions.retransmission, true, + min(wirelessOptions.maxPlayers, LINK_UNIVERSAL_MAX_PLAYERS), wirelessOptions.timeout, wirelessOptions.remoteTimeout, wirelessOptions.interval, wirelessOptions.sendTimerId, wirelessOptions.asyncACKTimerId); diff --git a/lib/LinkWireless.hpp b/lib/LinkWireless.hpp index ebc7641..9520046 100644 --- a/lib/LinkWireless.hpp +++ b/lib/LinkWireless.hpp @@ -55,6 +55,7 @@ // -------------------------------------------------------------------------- #include +#include #include #include "LinkGPIO.hpp" #include "LinkSPI.hpp" @@ -882,7 +883,8 @@ class LinkWireless { case LINK_WIRELESS_COMMAND_ACCEPT_CONNECTIONS: { // AcceptConnections (end) u8 oldPlayerCount = sessionState.playerCount; - sessionState.playerCount = 1 + asyncCommand.result.responsesSize; + sessionState.playerCount = + min(1 + asyncCommand.result.responsesSize, config.maxPlayers); if (sessionState.playerCount > oldPlayerCount && sessionState.playerCount == config.maxPlayers) { From f8e9dde5ec6a53e814c4082ec04b522cc435cfd1 Mon Sep 17 00:00:00 2001 From: Rodrigo Alfonso Date: Thu, 4 Jan 2024 01:29:25 -0300 Subject: [PATCH 02/10] Adding maxPlayers to wireless adapter documentation --- docs/wireless_adapter.md | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/wireless_adapter.md b/docs/wireless_adapter.md index 28f4035..c9d2f69 100644 --- a/docs/wireless_adapter.md +++ b/docs/wireless_adapter.md @@ -233,6 +233,14 @@ Whenever either side expects something to be sent from the other (as SPI is alwa Both Pokemon games and the multiboot ROM that the adapter sends when no cartridge is inserted use `0x003C0420`. +🔝 For a game, the most important bits are bits `16-17` (let's call this `maxPlayers`), which specify the maximum number of allowed players: +- `00`: 5 players (1 host and 4 clients) +- `01`: 4 players +- `10`: 3 players +- `11`: 2 players + +⚠️ Clients must always set `maxPlayers` to `00`. + #### Broadcast - `0x16` [![Image without alt text or caption](img/0x16.png)](img/0x16.png) @@ -265,14 +273,22 @@ Both Pokemon games and the multiboot ROM that the adapter sends when no cartridg - Clients cannot connect, even if they already know the host ID (`FinishConnection` will fail). - Calls to `AcceptConnections` on the host side will fail. -#### BroadcastRead - `0x1d`, `0x1e` and `0x1c` +#### BroadcastRead - `0x1c`, `0x1d` and `0x1e` [![Image without alt text or caption](img/0x1d.png)](img/0x1d.png) -* Send length: 0, response length: 7 \* number of broadcasts +* Send length: 0, response length: 7 \* number of broadcasts (maximum: 4) -* All currently broadcasting devices are returned here along with an ID at the start of each. -* IDs have 16 bits. +* All currently broadcasting devices are returned here along with a word of **metadata** (the metadata word first, then 6 words with broadcast data). +* The metadata contains: + * First 2 bytes: Server ID. IDs have 16 bits. + * 3rd byte: Available slots. This can be used to check whether a player can join a room or not. + * `0b00`: No one is connected yet (just the host). + * `0b01`: There is 1 connected client, and there's room for more. + * `0b10`: There are 2 connected clients, and there's room for more. + * `0b11`: There are 3 connected clients, and there's room for more. + * `0xff`: The server is full. The number of connected players is unknown, as it depends on `maxPlayers` (see [Setup](#setup---0x17)). + * 4th byte: Zero. 🆔 IDs are randomly generated. Each time you broadcast or connect, the adapter assigns you a new id. @@ -297,7 +313,7 @@ Both Pokemon games and the multiboot ROM that the adapter sends when no cartridg * Send length: 1, response length: 0 -* Send the ID of the adapter you want to connect to from [BroadcastRead](#broadcastread---0x1d-0x1e-and-0x1c). +* Send the ID of the adapter you want to connect to from [BroadcastRead](#broadcastread---0x1c-0x1d-and-0x1e). #### IsFinishedConnect - `0x20` From b537e6ab7181bce867831dbfb47cf7a2b8c3d956 Mon Sep 17 00:00:00 2001 From: Rodrigo Alfonso Date: Thu, 4 Jan 2024 01:48:43 -0300 Subject: [PATCH 03/10] FIX: Ensuring that the wireless adapter is serving before autoclosing the room --- README.md | 2 +- lib/LinkUniversal.hpp | 8 ++++---- lib/LinkWireless.hpp | 7 +++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index a09960f..8135b64 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,7 @@ Name | Return type | Description `isActive()` | **bool** | Returns whether the library is active or not. `activate()` | **bool** | Activates the library. When an adapter is connected, it changes the state to `AUTHENTICATED`. It can also be used to disconnect or reset the adapter. `deactivate()` | **bool** | Puts the adapter into a low consumption mode and then deactivates the library. It returns a boolean indicating whether the transition to low consumption mode was successful. -`serve([gameName], [userName], [gameId], [isUpdate])` | **bool** | Starts broadcasting a server and changes the state to `SERVING`. You can, optionally, provide a `gameName` (max `14` characters), a `userName` (max `8` characters), and a `gameId` *(0 ~ 0x7FFF)* that games will be able to read. If `isUpdate` is true, this method only updates the broadcast data. +`serve([gameName], [userName], [gameId])` | **bool** | Starts broadcasting a server and changes the state to `SERVING`. You can, optionally, provide a `gameName` (max `14` characters), a `userName` (max `8` characters), and a `gameId` *(0 ~ 0x7FFF)* that games will be able to read. If the adapter is already serving, this method only updates the broadcast data. `getServers(servers, [onWait])` | **bool** | Fills the `servers` array with all the currently broadcasting servers. This action takes 1 second to complete, but you can optionally provide an `onWait()` function which will be invoked each time VBlank starts. `getServersAsyncStart()` | **bool** | Starts looking for broadcasting servers and changes the state to `SEARCHING`. After this, call `getServersAsyncEnd(...)` 1 second later. `getServersAsyncEnd(servers)` | **bool** | Fills the `servers` array with all the currently broadcasting servers. Changes the state to `AUTHENTICATED` again. diff --git a/lib/LinkUniversal.hpp b/lib/LinkUniversal.hpp index 146a426..257ccb6 100644 --- a/lib/LinkUniversal.hpp +++ b/lib/LinkUniversal.hpp @@ -213,12 +213,12 @@ class LinkUniversal { receiveWirelessMessages(); - if (!linkWireless->_hasActiveAsyncCommand() && + if (linkWireless->getState() == LinkWireless::State::SERVING && + !didCloseWirelessRoom && linkWireless->playerCount() == linkWireless->config.maxPlayers && - !didCloseWirelessRoom) { + !linkWireless->_hasActiveAsyncCommand()) { linkWireless->serve(config.gameName, - LINK_UNIVERSAL_FULL_ROOM_NUMBER_STR, - LINK_WIRELESS_MAX_GAME_ID, true); + LINK_UNIVERSAL_FULL_ROOM_NUMBER_STR); didCloseWirelessRoom = true; } } diff --git a/lib/LinkWireless.hpp b/lib/LinkWireless.hpp index 9520046..a3cf97d 100644 --- a/lib/LinkWireless.hpp +++ b/lib/LinkWireless.hpp @@ -252,10 +252,9 @@ class LinkWireless { bool serve(std::string gameName = "", std::string userName = "", - u16 gameId = LINK_WIRELESS_MAX_GAME_ID, - bool isUpdate = false) { + u16 gameId = LINK_WIRELESS_MAX_GAME_ID) { LINK_WIRELESS_RESET_IF_NEEDED - if (state != AUTHENTICATED && (!isUpdate || state != SERVING)) { + if (state != AUTHENTICATED && state != SERVING) { lastError = WRONG_STATE; return false; } @@ -286,7 +285,7 @@ class LinkWireless { bool success = sendCommand(LINK_WIRELESS_COMMAND_BROADCAST, true).success; - if (!isUpdate) { + if (state != SERVING) { success = success && sendCommand(LINK_WIRELESS_COMMAND_START_HOST).success; } From 46f257c01588bd908f114b39d3289405691238b2 Mon Sep 17 00:00:00 2001 From: Rodrigo Alfonso Date: Thu, 4 Jan 2024 02:12:09 -0300 Subject: [PATCH 04/10] Using native wireless adapter's support for maxPlayers instead of using EndHost & updating broadcast data --- examples/LinkUniversal_basic/src/main.cpp | 22 ++++++++++++-- examples/LinkWireless_demo/src/main.cpp | 9 ++++-- lib/LinkCable.hpp | 2 +- lib/LinkCableMultiboot.hpp | 2 +- lib/LinkGPIO.hpp | 2 +- lib/LinkSPI.hpp | 2 +- lib/LinkUniversal.hpp | 19 ++---------- lib/LinkWireless.hpp | 35 +++++++++++++---------- 8 files changed, 53 insertions(+), 40 deletions(-) diff --git a/examples/LinkUniversal_basic/src/main.cpp b/examples/LinkUniversal_basic/src/main.cpp index 474b3f6..4c48408 100644 --- a/examples/LinkUniversal_basic/src/main.cpp +++ b/examples/LinkUniversal_basic/src/main.cpp @@ -21,10 +21,10 @@ void init() { int main() { init(); - log("Press A to start\n\n\n\n\n\n\n\n\nhold LEFT on start:\n -> force " + log("Press A to start\n\n\n\n\nhold LEFT on start:\n -> force " "cable\n\nhold RIGHT on start:\n -> force wireless\n\nhold UP on " "start:\n -> force wireless server\n\nhold DOWN on start:\n -> force " - "wireless client"); + "wireless client\n\nhold B on start:\n -> set 2 players (wireless)"); waitFor(KEY_A); u16 initialKeys = ~REG_KEYS & KEY_ANY; bool forceCable = initialKeys & KEY_LEFT; @@ -37,9 +37,25 @@ int main() { : forceWirelessServer ? LinkUniversal::Protocol::WIRELESS_SERVER : forceWirelessClient ? LinkUniversal::Protocol::WIRELESS_CLIENT : LinkUniversal::Protocol::AUTODETECT; + u32 maxPlayers = (initialKeys & KEY_B) ? 2 : LINK_UNIVERSAL_MAX_PLAYERS; // (1) Create a LinkUniversal instance - linkUniversal = new LinkUniversal(protocol); + linkUniversal = new LinkUniversal( + protocol, "LinkUNI", + (LinkUniversal::CableOptions){ + .baudRate = LinkCable::BAUD_RATE_1, + .timeout = LINK_CABLE_DEFAULT_TIMEOUT, + .remoteTimeout = LINK_CABLE_DEFAULT_REMOTE_TIMEOUT, + .interval = LINK_CABLE_DEFAULT_INTERVAL, + .sendTimerId = LINK_CABLE_DEFAULT_SEND_TIMER_ID}, + (LinkUniversal::WirelessOptions){ + .retransmission = true, + .maxPlayers = maxPlayers, + .timeout = LINK_WIRELESS_DEFAULT_TIMEOUT, + .remoteTimeout = LINK_WIRELESS_DEFAULT_REMOTE_TIMEOUT, + .interval = LINK_WIRELESS_DEFAULT_INTERVAL, + .sendTimerId = LINK_WIRELESS_DEFAULT_SEND_TIMER_ID, + .asyncACKTimerId = LINK_WIRELESS_DEFAULT_ASYNC_ACK_TIMER_ID}); // (2) Add the required interrupt service routines interrupt_init(); diff --git a/examples/LinkWireless_demo/src/main.cpp b/examples/LinkWireless_demo/src/main.cpp index 8a76419..b4772a7 100644 --- a/examples/LinkWireless_demo/src/main.cpp +++ b/examples/LinkWireless_demo/src/main.cpp @@ -203,8 +203,13 @@ void connect() { if (server.id == LINK_WIRELESS_END) break; - str += std::to_string(server.id) + " (" + std::to_string(server.gameId) + - ")\n"; + str += + std::to_string(server.id) + + (server.isFull() ? " [full]" + : " [" + std::to_string(server.currentPlayerCount) + + " online]") + + "\n"; + str += " -> gameID: " + std::to_string(server.gameId) + "\n"; if (server.gameName.length() > 0) str += " -> game: " + server.gameName + "\n"; if (server.userName.length() > 0) diff --git a/lib/LinkCable.hpp b/lib/LinkCable.hpp index 6d4383d..b208bd5 100644 --- a/lib/LinkCable.hpp +++ b/lib/LinkCable.hpp @@ -62,7 +62,7 @@ #define LINK_CABLE_BIT_GENERAL_PURPOSE_HIGH 15 #define LINK_CABLE_BARRIER asm volatile("" ::: "memory") -static volatile char LINK_CABLE_VERSION[] = "LinkCable/v6.0.2"; +static volatile char LINK_CABLE_VERSION[] = "LinkCable/v6.0.3"; void LINK_CABLE_ISR_VBLANK(); void LINK_CABLE_ISR_SERIAL(); diff --git a/lib/LinkCableMultiboot.hpp b/lib/LinkCableMultiboot.hpp index 66520f5..9e1addd 100644 --- a/lib/LinkCableMultiboot.hpp +++ b/lib/LinkCableMultiboot.hpp @@ -58,7 +58,7 @@ return error(FAILURE_DURING_HANDSHAKE); static volatile char LINK_CABLE_MULTIBOOT_VERSION[] = - "LinkCableMultiboot/v6.0.2"; + "LinkCableMultiboot/v6.0.3"; const u8 LINK_CABLE_MULTIBOOT_CLIENT_IDS[] = {0b0010, 0b0100, 0b1000}; diff --git a/lib/LinkGPIO.hpp b/lib/LinkGPIO.hpp index ed046be..3cda63a 100644 --- a/lib/LinkGPIO.hpp +++ b/lib/LinkGPIO.hpp @@ -35,7 +35,7 @@ else \ REG &= ~(1 << BIT); -static volatile char LINK_GPIO_VERSION[] = "LinkGPIO/v6.0.2"; +static volatile char LINK_GPIO_VERSION[] = "LinkGPIO/v6.0.3"; const u8 LINK_GPIO_DATA_BITS[] = {2, 3, 1, 0}; const u8 LINK_GPIO_DIRECTION_BITS[] = {6, 7, 5, 4}; diff --git a/lib/LinkSPI.hpp b/lib/LinkSPI.hpp index 9159268..176b668 100644 --- a/lib/LinkSPI.hpp +++ b/lib/LinkSPI.hpp @@ -49,7 +49,7 @@ #define LINK_SPI_BIT_GENERAL_PURPOSE_LOW 14 #define LINK_SPI_BIT_GENERAL_PURPOSE_HIGH 15 -static volatile char LINK_SPI_VERSION[] = "LinkSPI/v6.0.2"; +static volatile char LINK_SPI_VERSION[] = "LinkSPI/v6.0.3"; class LinkSPI { public: diff --git a/lib/LinkUniversal.hpp b/lib/LinkUniversal.hpp index 257ccb6..d8fd98c 100644 --- a/lib/LinkUniversal.hpp +++ b/lib/LinkUniversal.hpp @@ -48,8 +48,6 @@ #define LINK_UNIVERSAL_DISCONNECTED LINK_CABLE_DISCONNECTED #define LINK_UNIVERSAL_NO_DATA LINK_CABLE_NO_DATA #define LINK_UNIVERSAL_MAX_ROOM_NUMBER 32000 -#define LINK_UNIVERSAL_FULL_ROOM_NUMBER 32001 -#define LINK_UNIVERSAL_FULL_ROOM_NUMBER_STR "32001" #define LINK_UNIVERSAL_INIT_WAIT_FRAMES 10 #define LINK_UNIVERSAL_SWITCH_WAIT_FRAMES 25 #define LINK_UNIVERSAL_SWITCH_WAIT_FRAMES_RANDOM 10 @@ -57,7 +55,7 @@ #define LINK_UNIVERSAL_SERVE_WAIT_FRAMES 60 #define LINK_UNIVERSAL_SERVE_WAIT_FRAMES_RANDOM 30 -static volatile char LINK_UNIVERSAL_VERSION[] = "LinkUniversal/v6.0.2"; +static volatile char LINK_UNIVERSAL_VERSION[] = "LinkUniversal/v6.0.3"; void LINK_UNIVERSAL_ISR_VBLANK(); void LINK_UNIVERSAL_ISR_SERIAL(); @@ -212,15 +210,6 @@ class LinkUniversal { } receiveWirelessMessages(); - - if (linkWireless->getState() == LinkWireless::State::SERVING && - !didCloseWirelessRoom && - linkWireless->playerCount() == linkWireless->config.maxPlayers && - !linkWireless->_hasActiveAsyncCommand()) { - linkWireless->serve(config.gameName, - LINK_UNIVERSAL_FULL_ROOM_NUMBER_STR); - didCloseWirelessRoom = true; - } } break; @@ -318,7 +307,6 @@ class LinkUniversal { u32 switchWait = 0; u32 subWaitCount = 0; u32 serveWait = 0; - bool didCloseWirelessRoom = false; volatile bool isEnabled = false; void receiveCableMessages() { @@ -395,10 +383,10 @@ class LinkUniversal { if (server.id == LINK_WIRELESS_END) break; - if (server.gameName == config.gameName) { + if (!server.isFull() && server.gameName == config.gameName) { u32 randomNumber = safeStoi(server.userName); if (randomNumber > maxRandomNumber && - randomNumber < LINK_UNIVERSAL_FULL_ROOM_NUMBER) { + randomNumber < LINK_UNIVERSAL_MAX_ROOM_NUMBER) { maxRandomNumber = randomNumber; serverIndex = i; } @@ -493,7 +481,6 @@ class LinkUniversal { serveWait = 0; for (u32 i = 0; i < LINK_UNIVERSAL_MAX_PLAYERS; i++) incomingMessages[i].clear(); - didCloseWirelessRoom = false; } u32 safeStoi(const std::string& str) { diff --git a/lib/LinkWireless.hpp b/lib/LinkWireless.hpp index a3cf97d..26dc22e 100644 --- a/lib/LinkWireless.hpp +++ b/lib/LinkWireless.hpp @@ -103,6 +103,7 @@ #define LINK_WIRELESS_RESPONSE_ACK 0x80 #define LINK_WIRELESS_DATA_REQUEST 0x80000000 #define LINK_WIRELESS_SETUP_MAGIC 0x003c0420 +#define LINK_WIRELESS_SETUP_MAX_PLAYERS_BIT 16 #define LINK_WIRELESS_STILL_CONNECTING 0x01000000 #define LINK_WIRELESS_BROADCAST_LENGTH 6 #define LINK_WIRELESS_BROADCAST_RESPONSE_LENGTH \ @@ -117,7 +118,6 @@ #define LINK_WIRELESS_COMMAND_BROADCAST 0x16 #define LINK_WIRELESS_COMMAND_START_HOST 0x19 #define LINK_WIRELESS_COMMAND_ACCEPT_CONNECTIONS 0x1a -#define LINK_WIRELESS_COMMAND_END_HOST 0x1b #define LINK_WIRELESS_COMMAND_BROADCAST_READ_START 0x1c #define LINK_WIRELESS_COMMAND_BROADCAST_READ_POLL 0x1d #define LINK_WIRELESS_COMMAND_BROADCAST_READ_END 0x1e @@ -139,7 +139,7 @@ if (!reset()) \ return false; -static volatile char LINK_WIRELESS_VERSION[] = "LinkWireless/v6.0.2"; +static volatile char LINK_WIRELESS_VERSION[] = "LinkWireless/v6.0.3"; void LINK_WIRELESS_ISR_VBLANK(); void LINK_WIRELESS_ISR_SERIAL(); @@ -204,6 +204,9 @@ class LinkWireless { u16 gameId; std::string gameName; std::string userName; + u8 currentPlayerCount; + + bool isFull() { return currentPlayerCount == 0; } }; explicit LinkWireless( @@ -269,6 +272,9 @@ class LinkWireless { gameName.append(LINK_WIRELESS_MAX_GAME_NAME_LENGTH - gameName.length(), 0); userName.append(LINK_WIRELESS_MAX_USER_NAME_LENGTH - userName.length(), 0); + if (state != SERVING) + setup(config.maxPlayers); + addData(buildU32(buildU16(gameName[1], gameName[0]), gameId & LINK_WIRELESS_MAX_GAME_ID), true); @@ -382,6 +388,9 @@ class LinkWireless { recoverName(server.gameName, result.responses[start + 4]); recoverName(server.userName, result.responses[start + 5]); recoverName(server.userName, result.responses[start + 6]); + u8 connectedClients = (result.responses[start] >> 16) & 0xff; + server.currentPlayerCount = + connectedClients == 0xff ? 0 : (1 + connectedClients); servers[i] = server; } @@ -881,22 +890,11 @@ class LinkWireless { switch (asyncCommand.type) { case LINK_WIRELESS_COMMAND_ACCEPT_CONNECTIONS: { // AcceptConnections (end) - u8 oldPlayerCount = sessionState.playerCount; sessionState.playerCount = min(1 + asyncCommand.result.responsesSize, config.maxPlayers); - if (sessionState.playerCount > oldPlayerCount && - sessionState.playerCount == config.maxPlayers) { - // EndHost (start) - sendCommandAsync(LINK_WIRELESS_COMMAND_END_HOST); - } - break; } - // case LINK_WIRELESS_COMMAND_END_HOST: { - // // EndHost (end) - // break; - // } case LINK_WIRELESS_COMMAND_SEND_DATA: { // SendData (end) @@ -1363,8 +1361,7 @@ class LinkWireless { if (!sendCommand(LINK_WIRELESS_COMMAND_HELLO).success) return false; - addData(LINK_WIRELESS_SETUP_MAGIC, true); - if (!sendCommand(LINK_WIRELESS_COMMAND_SETUP, true).success) + if (!setup()) return false; linkSPI->activate(LinkSPI::Mode::MASTER_2MBPS); @@ -1423,6 +1420,14 @@ class LinkWireless { return true; } + bool setup(u8 maxPlayers = LINK_WIRELESS_MAX_PLAYERS) { + addData(LINK_WIRELESS_SETUP_MAGIC | + (((LINK_WIRELESS_MAX_PLAYERS - maxPlayers) & 0b11) + << LINK_WIRELESS_SETUP_MAX_PLAYERS_BIT), + true); + return sendCommand(LINK_WIRELESS_COMMAND_SETUP, true).success; + } + CommandResult sendCommand(u8 type, bool withData = false) { CommandResult result; u32 command = buildCommand(type, withData ? (u16)nextCommandDataSize : 0); From 6c0f40805ae0b5ace0f8c909fdd9f6f87b2b47e4 Mon Sep 17 00:00:00 2001 From: Rodrigo Alfonso Date: Sat, 6 Jan 2024 02:19:41 -0300 Subject: [PATCH 05/10] Using LINK_WIRELESS_PUT_ISR_IN_IWRAM in the LinkUniversal_basic example --- examples/compile.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/compile.sh b/examples/compile.sh index 66ddf85..22faf96 100644 --- a/examples/compile.sh +++ b/examples/compile.sh @@ -31,8 +31,10 @@ cp LinkSPI_demo.gba ../ cd .. cd LinkUniversal_basic/ +sed -i -e "s/\/\/ #define LINK_WIRELESS_PUT_ISR_IN_IWRAM/#define LINK_WIRELESS_PUT_ISR_IN_IWRAM/g" ../../lib/LinkWireless.hpp make rebuild cp LinkUniversal_basic.gba ../ +sed -i -e "s/#define LINK_WIRELESS_PUT_ISR_IN_IWRAM/\/\/ #define LINK_WIRELESS_PUT_ISR_IN_IWRAM/g" ../../lib/LinkWireless.hpp cd .. cd LinkCable_full/ From 67926404d25ce02575c7885732d427709d7fc03f Mon Sep 17 00:00:00 2001 From: Rodrigo Alfonso Date: Sat, 6 Jan 2024 04:00:50 -0300 Subject: [PATCH 06/10] FIX: Leaked messages from previous session (v6.0.0 regression) --- lib/LinkWireless.hpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/lib/LinkWireless.hpp b/lib/LinkWireless.hpp index 26dc22e..b9af91e 100644 --- a/lib/LinkWireless.hpp +++ b/lib/LinkWireless.hpp @@ -485,6 +485,11 @@ class LinkWireless { isAddingMessage = false; LINK_WIRELESS_BARRIER; + if (isPendingClearActive) { + sessionState.tmpMessagesToSend.clear(); + isPendingClearActive = false; + } + return true; } @@ -864,6 +869,7 @@ class LinkWireless { u32 nextCommandDataSize = 0; volatile bool isReadingMessages = false; volatile bool isAddingMessage = false; + volatile bool isPendingClearActive = false; Error lastError = NONE; volatile bool isEnabled = false; @@ -1238,15 +1244,12 @@ class LinkWireless { return; while (!sessionState.tmpMessagesToSend.isEmpty()) { - if (isSessionActive() && !_canSend()) + if (!_canSend()) break; auto message = sessionState.tmpMessagesToSend.pop(); - - if (isSessionActive()) { - message.packetId = newPacketId(); - sessionState.outgoingMessages.push(message); - } + message.packetId = newPacketId(); + sessionState.outgoingMessages.push(message); } } @@ -1256,9 +1259,7 @@ class LinkWireless { while (!sessionState.tmpMessagesToReceive.isEmpty()) { auto message = sessionState.tmpMessagesToReceive.pop(); - - if (state == SERVING || state == CONNECTED) - sessionState.incomingMessages.push(message); + sessionState.incomingMessages.push(message); } } @@ -1337,6 +1338,12 @@ class LinkWireless { if (!isReadingMessages) this->sessionState.incomingMessages.clear(); this->sessionState.outgoingMessages.clear(); + + this->sessionState.tmpMessagesToReceive.clear(); + if (!isAddingMessage) + this->sessionState.tmpMessagesToSend.clear(); + else + isPendingClearActive = true; } void stop() { From 4dec5efa2a4e511eff63895e200c83844bccdba7 Mon Sep 17 00:00:00 2001 From: Rodrigo Alfonso Date: Sat, 6 Jan 2024 05:05:41 -0300 Subject: [PATCH 07/10] Adding lag option to wireless demo --- examples/LinkWireless_demo/src/main.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/examples/LinkWireless_demo/src/main.cpp b/examples/LinkWireless_demo/src/main.cpp index b4772a7..ac626b2 100644 --- a/examples/LinkWireless_demo/src/main.cpp +++ b/examples/LinkWireless_demo/src/main.cpp @@ -27,6 +27,7 @@ void connect(); void messageLoop(); void log(std::string text); void waitFor(u16 key); +void wait(u32 verticalLines); void hang(); LinkWireless::Error lastError; @@ -432,6 +433,10 @@ void messageLoop() { #endif } + // Test lag + if (keys & KEY_DOWN) + wait(9000); + // Print VBlankIntrWait(); log(output); @@ -451,6 +456,18 @@ void waitFor(u16 key) { } while (!(keys & key)); } +void wait(u32 verticalLines) { + u32 count = 0; + u32 vCount = REG_VCOUNT; + + while (count < verticalLines) { + if (REG_VCOUNT != vCount) { + count += max((int)REG_VCOUNT - (int)vCount, 0); + vCount = REG_VCOUNT; + } + }; +} + void hang() { waitFor(KEY_DOWN); } \ No newline at end of file From f07a98834a55c4954fd1a43c908936af69537a89 Mon Sep 17 00:00:00 2001 From: Rodrigo Alfonso Date: Sat, 6 Jan 2024 06:18:05 -0300 Subject: [PATCH 08/10] FIX: Invalid memory access in LinkUniversal --- examples/LinkWireless_demo/src/main.cpp | 4 ++-- lib/LinkUniversal.hpp | 4 ++-- lib/LinkWireless.hpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/LinkWireless_demo/src/main.cpp b/examples/LinkWireless_demo/src/main.cpp index ac626b2..6ef7789 100644 --- a/examples/LinkWireless_demo/src/main.cpp +++ b/examples/LinkWireless_demo/src/main.cpp @@ -314,10 +314,10 @@ void messageLoop() { sending = false; // (7) Receive data - LinkWireless::Message messages[LINK_WIRELESS_MAX_TRANSFER_LENGTH]; + LinkWireless::Message messages[LINK_WIRELESS_QUEUE_SIZE]; linkWireless->receive(messages); if (messages[0].packetId != LINK_WIRELESS_END) { - for (u32 i = 0; i < LINK_WIRELESS_MAX_TRANSFER_LENGTH; i++) { + for (u32 i = 0; i < LINK_WIRELESS_QUEUE_SIZE; i++) { auto message = messages[i]; if (message.packetId == LINK_WIRELESS_END) break; diff --git a/lib/LinkUniversal.hpp b/lib/LinkUniversal.hpp index d8fd98c..c8322da 100644 --- a/lib/LinkUniversal.hpp +++ b/lib/LinkUniversal.hpp @@ -317,10 +317,10 @@ class LinkUniversal { } void receiveWirelessMessages() { - LinkWireless::Message messages[LINK_WIRELESS_MAX_TRANSFER_LENGTH]; + LinkWireless::Message messages[LINK_WIRELESS_QUEUE_SIZE]; linkWireless->receive(messages); - for (u32 i = 0; i < LINK_WIRELESS_MAX_TRANSFER_LENGTH; i++) { + for (u32 i = 0; i < LINK_WIRELESS_QUEUE_SIZE; i++) { auto message = messages[i]; if (message.packetId == LINK_WIRELESS_END) break; diff --git a/lib/LinkWireless.hpp b/lib/LinkWireless.hpp index b9af91e..bbf43b8 100644 --- a/lib/LinkWireless.hpp +++ b/lib/LinkWireless.hpp @@ -37,7 +37,7 @@ // - 6) Send data: // linkWireless->send(0x1234); // - 7) Receive data: -// LinkWireless::Message messages[LINK_WIRELESS_MAX_TRANSFER_LENGTH]; +// LinkWireless::Message messages[LINK_WIRELESS_QUEUE_SIZE]; // linkWireless->receive(messages); // if (messages[0].packetId != LINK_WIRELESS_END) { // // ... From 732776129ab30beda90691435b090c9893beccb7 Mon Sep 17 00:00:00 2001 From: Rodrigo Alfonso Date: Sat, 6 Jan 2024 06:52:13 -0300 Subject: [PATCH 09/10] Limiting server list to 3 in wireless demo --- examples/LinkWireless_demo/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/LinkWireless_demo/src/main.cpp b/examples/LinkWireless_demo/src/main.cpp index 6ef7789..865a796 100644 --- a/examples/LinkWireless_demo/src/main.cpp +++ b/examples/LinkWireless_demo/src/main.cpp @@ -199,7 +199,7 @@ void connect() { return; } else { std::string str = "Press START to connect\n(first ID will be used)\n\n"; - for (u32 i = 0; i < LINK_WIRELESS_MAX_SERVERS; i++) { + for (u32 i = 0; i < 3; i++) { auto server = servers[i]; if (server.id == LINK_WIRELESS_END) break; @@ -425,7 +425,7 @@ void messageLoop() { #ifndef PROFILING_ENABLED if (lostPackets > 0) { output += "\n\n_lostPackets: " + std::to_string(lostPackets) + "\n"; - output += "_last: (" + std::to_string(lastLostPacketPlayerId) + "->" + + output += "_last: (" + std::to_string(lastLostPacketPlayerId) + ":" + std::to_string(lastLostPacketReceivedPacketId) + ") " + std::to_string(lastLostPacketReceived) + " [vs " + std::to_string(lastLostPacketExpected) + "]"; From 8df5c69bf0ec09cb20a2fdd60ea7e4b85973438d Mon Sep 17 00:00:00 2001 From: Rodrigo Alfonso Date: Sat, 6 Jan 2024 07:25:45 -0300 Subject: [PATCH 10/10] Using normal wait in LinkWireless --- examples/LinkWireless_demo/src/main.cpp | 2 +- lib/LinkWireless.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/LinkWireless_demo/src/main.cpp b/examples/LinkWireless_demo/src/main.cpp index 865a796..73877e6 100644 --- a/examples/LinkWireless_demo/src/main.cpp +++ b/examples/LinkWireless_demo/src/main.cpp @@ -462,7 +462,7 @@ void wait(u32 verticalLines) { while (count < verticalLines) { if (REG_VCOUNT != vCount) { - count += max((int)REG_VCOUNT - (int)vCount, 0); + count++; vCount = REG_VCOUNT; } }; diff --git a/lib/LinkWireless.hpp b/lib/LinkWireless.hpp index bbf43b8..e63bfbd 100644 --- a/lib/LinkWireless.hpp +++ b/lib/LinkWireless.hpp @@ -1612,7 +1612,7 @@ class LinkWireless { bool timeout(u32 limit, u32& lines, u32& vCount) { if (REG_VCOUNT != vCount) { - lines += std::max((int)REG_VCOUNT - (int)vCount, 0); + lines += max((int)REG_VCOUNT - (int)vCount, 0); vCount = REG_VCOUNT; } @@ -1625,7 +1625,7 @@ class LinkWireless { while (count < verticalLines) { if (REG_VCOUNT != vCount) { - count += std::max((int)REG_VCOUNT - (int)vCount, 0); + count++; vCount = REG_VCOUNT; } };