Merge pull request #15 from afska/v6.0.3

📻🌎 Native wireless adapter support for maxPlayers & Bugfixing
This commit is contained in:
Rodrigo Alfonso
2024-01-06 07:35:19 -03:00
committed by GitHub
11 changed files with 129 additions and 71 deletions

View File

@@ -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.

View File

@@ -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`

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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/

View File

@@ -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();

View File

@@ -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};

View File

@@ -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};

View File

@@ -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:

View File

@@ -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) {

View File

@@ -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;
}
};