mirror of
https://github.com/afska/gba-link-connection.git
synced 2026-10-02 13:56:42 -05:00
Merge pull request #15 from afska/v6.0.3
📻🌎 Native wireless adapter support for maxPlayers & Bugfixing
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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`
|
||||
|
||||
[](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`
|
||||
|
||||
[](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`
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
@@ -198,13 +199,18 @@ 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;
|
||||
|
||||
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)
|
||||
@@ -308,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;
|
||||
@@ -419,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) + "]";
|
||||
@@ -427,6 +433,10 @@ void messageLoop() {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Test lag
|
||||
if (keys & KEY_DOWN)
|
||||
wait(9000);
|
||||
|
||||
// Print
|
||||
VBlankIntrWait();
|
||||
log(output);
|
||||
@@ -446,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++;
|
||||
vCount = REG_VCOUNT;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void hang() {
|
||||
waitFor(KEY_DOWN);
|
||||
}
|
||||
@@ -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/
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
#include <tonc_bios.h>
|
||||
#include <tonc_core.h>
|
||||
#include <tonc_math.h>
|
||||
#include "LinkCable.hpp"
|
||||
#include "LinkWireless.hpp"
|
||||
|
||||
@@ -47,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
|
||||
@@ -56,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();
|
||||
@@ -101,7 +100,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 +108,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);
|
||||
@@ -210,15 +210,6 @@ class LinkUniversal {
|
||||
}
|
||||
|
||||
receiveWirelessMessages();
|
||||
|
||||
if (!linkWireless->_hasActiveAsyncCommand() &&
|
||||
linkWireless->playerCount() == linkWireless->config.maxPlayers &&
|
||||
!didCloseWirelessRoom) {
|
||||
linkWireless->serve(config.gameName,
|
||||
LINK_UNIVERSAL_FULL_ROOM_NUMBER_STR,
|
||||
LINK_WIRELESS_MAX_GAME_ID, true);
|
||||
didCloseWirelessRoom = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -316,7 +307,6 @@ class LinkUniversal {
|
||||
u32 switchWait = 0;
|
||||
u32 subWaitCount = 0;
|
||||
u32 serveWait = 0;
|
||||
bool didCloseWirelessRoom = false;
|
||||
volatile bool isEnabled = false;
|
||||
|
||||
void receiveCableMessages() {
|
||||
@@ -327,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;
|
||||
@@ -393,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;
|
||||
}
|
||||
@@ -491,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) {
|
||||
|
||||
@@ -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) {
|
||||
// // ...
|
||||
@@ -55,6 +55,7 @@
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#include <tonc_core.h>
|
||||
#include <tonc_math.h>
|
||||
#include <string>
|
||||
#include "LinkGPIO.hpp"
|
||||
#include "LinkSPI.hpp"
|
||||
@@ -102,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 \
|
||||
@@ -116,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
|
||||
@@ -138,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();
|
||||
@@ -203,6 +204,9 @@ class LinkWireless {
|
||||
u16 gameId;
|
||||
std::string gameName;
|
||||
std::string userName;
|
||||
u8 currentPlayerCount;
|
||||
|
||||
bool isFull() { return currentPlayerCount == 0; }
|
||||
};
|
||||
|
||||
explicit LinkWireless(
|
||||
@@ -251,10 +255,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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -285,7 +291,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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -476,6 +485,11 @@ class LinkWireless {
|
||||
isAddingMessage = false;
|
||||
LINK_WIRELESS_BARRIER;
|
||||
|
||||
if (isPendingClearActive) {
|
||||
sessionState.tmpMessagesToSend.clear();
|
||||
isPendingClearActive = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -855,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;
|
||||
|
||||
@@ -881,21 +896,11 @@ class LinkWireless {
|
||||
switch (asyncCommand.type) {
|
||||
case LINK_WIRELESS_COMMAND_ACCEPT_CONNECTIONS: {
|
||||
// AcceptConnections (end)
|
||||
u8 oldPlayerCount = sessionState.playerCount;
|
||||
sessionState.playerCount = 1 + asyncCommand.result.responsesSize;
|
||||
|
||||
if (sessionState.playerCount > oldPlayerCount &&
|
||||
sessionState.playerCount == config.maxPlayers) {
|
||||
// EndHost (start)
|
||||
sendCommandAsync(LINK_WIRELESS_COMMAND_END_HOST);
|
||||
}
|
||||
sessionState.playerCount =
|
||||
min(1 + asyncCommand.result.responsesSize, config.maxPlayers);
|
||||
|
||||
break;
|
||||
}
|
||||
// case LINK_WIRELESS_COMMAND_END_HOST: {
|
||||
// // EndHost (end)
|
||||
// break;
|
||||
// }
|
||||
case LINK_WIRELESS_COMMAND_SEND_DATA: {
|
||||
// SendData (end)
|
||||
|
||||
@@ -1239,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1257,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1338,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() {
|
||||
@@ -1362,8 +1368,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);
|
||||
@@ -1422,6 +1427,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);
|
||||
@@ -1599,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;
|
||||
}
|
||||
|
||||
@@ -1612,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;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user