Migrating LinkRawWireless to static arrays

This commit is contained in:
Rodrigo Alfonso
2024-01-30 09:01:46 -03:00
parent 75aae7a279
commit f10ad006ae
4 changed files with 216 additions and 137 deletions

View File

@@ -111,6 +111,14 @@ void log(std::string string) {
scrollPageDown();
}
std::array<u32, LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH> toArray(
std::vector<u32> vector) {
std::array<u32, LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH> array;
for (u32 i = 0; i < vector.size(); i++)
array[i] = vector[i];
return array;
}
std::vector<Background*> DebugScene::backgrounds() {
return {};
}
@@ -473,7 +481,7 @@ void DebugScene::processCommand(u32 selectedCommandIndex) {
if (success) {
log("< [next slot] " +
linkRawWireless->toHex(response.nextClientNumber, 2));
for (u32 i = 0; i < response.connectedClients.size(); i++) {
for (u32 i = 0; i < response.connectedClientsSize; i++) {
log("< [client" +
std::to_string(response.connectedClients[i].clientNumber) +
"] " +
@@ -538,7 +546,7 @@ void DebugScene::processCommand(u32 selectedCommandIndex) {
bool success = linkRawWireless->acceptConnections(response);
if (success) {
for (u32 i = 0; i < response.connectedClients.size(); i++) {
for (u32 i = 0; i < response.connectedClientsSize; i++) {
log("< [client" +
std::to_string(response.connectedClients[i].clientNumber) +
"] " +
@@ -556,7 +564,7 @@ void DebugScene::processCommand(u32 selectedCommandIndex) {
bool success = linkRawWireless->endHost(response);
if (success) {
for (u32 i = 0; i < response.connectedClients.size(); i++) {
for (u32 i = 0; i < response.connectedClientsSize; i++) {
log("< [client" +
std::to_string(response.connectedClients[i].clientNumber) +
"] " +
@@ -580,11 +588,12 @@ void DebugScene::processCommand(u32 selectedCommandIndex) {
}
case 0x1d: {
return logOperation("sending " + name, [this]() {
std::vector<LinkRawWireless::Server> servers;
bool success = linkRawWireless->broadcastReadPoll(servers);
LinkRawWireless::BroadcastReadPollResponse response;
bool success = linkRawWireless->broadcastReadPoll(response);
if (success) {
for (u32 i = 0; i < servers.size(); i++) {
auto servers = response.servers;
for (u32 i = 0; i < response.serversSize; i++) {
serverIds[i] = servers[i].id;
log("< [room" + std::to_string(i) + ".id] " +
@@ -661,7 +670,7 @@ void DebugScene::processCommand(u32 selectedCommandIndex) {
data.erase(data.begin());
return logOperation("sending " + name, [&data, bytes]() {
return linkRawWireless->sendData(data, bytes);
return linkRawWireless->sendData(toArray(data), data.size(), bytes);
});
}
case 0x25: {
@@ -673,12 +682,12 @@ void DebugScene::processCommand(u32 selectedCommandIndex) {
return logOperation("sending " + name, [&data, bytes]() {
LinkRawWireless::RemoteCommand remoteCommand;
bool success =
linkRawWireless->sendDataAndWait(data, remoteCommand, bytes);
bool success = linkRawWireless->sendDataAndWait(
toArray(data), data.size(), remoteCommand, bytes);
if (success) {
log("< [notif] " + linkRawWireless->toHex(remoteCommand.commandId));
for (u32 i = 0; i < remoteCommand.params.size(); i++) {
for (u32 i = 0; i < remoteCommand.paramsSize; i++) {
log("< [param" + std::to_string(i) + "] " +
linkRawWireless->toHex(remoteCommand.params[i]));
}
@@ -699,7 +708,7 @@ void DebugScene::processCommand(u32 selectedCommandIndex) {
log("< [bytesC2] " + std::to_string(response.sentBytes[3]));
log("< [bytesC3] " + std::to_string(response.sentBytes[4]));
for (u32 i = 0; i < response.data.size(); i++)
for (u32 i = 0; i < response.dataSize; i++)
log("< [data" + std::to_string(i) + "] " +
linkRawWireless->toHex(response.data[i]));
}
@@ -714,7 +723,7 @@ void DebugScene::processCommand(u32 selectedCommandIndex) {
if (success) {
log("< [notif] " + linkRawWireless->toHex(remoteCommand.commandId));
for (u32 i = 0; i < remoteCommand.params.size(); i++) {
for (u32 i = 0; i < remoteCommand.paramsSize; i++) {
log("< [param" + std::to_string(i) + "] " +
linkRawWireless->toHex(remoteCommand.params[i]));
}
@@ -873,8 +882,8 @@ std::string DebugScene::selectUserName() {
void DebugScene::logGenericWaitCommand(std::string name, u32 id) {
auto data = selectData();
return logOperation("sending " + name, [id, &data]() {
auto result = linkRawWireless->sendCommand(id, data);
for (u32 i = 0; i < result.responses.size(); i++) {
auto result = linkRawWireless->sendCommand(id, toArray(data), data.size());
for (u32 i = 0; i < result.responsesSize; i++) {
log("< [response" + std::to_string(i) + "] " +
linkRawWireless->toHex(result.responses[i]));
}
@@ -889,7 +898,7 @@ void DebugScene::logGenericWaitCommand(std::string name, u32 id) {
if (remoteCommand.success) {
log("< [notif] " + linkRawWireless->toHex(remoteCommand.commandId));
for (u32 i = 0; i < remoteCommand.params.size(); i++) {
for (u32 i = 0; i < remoteCommand.paramsSize; i++) {
log("< [param" + std::to_string(i) + "] " +
linkRawWireless->toHex(remoteCommand.params[i]));
}
@@ -908,8 +917,9 @@ void DebugScene::logSimpleCommand(std::string name,
u32 id,
std::vector<u32> params) {
logOperation("sending " + name, [id, &params]() {
auto result = linkRawWireless->sendCommand(id, params);
for (u32 i = 0; i < result.responses.size(); i++) {
auto result =
linkRawWireless->sendCommand(id, toArray(params), params.size());
for (u32 i = 0; i < result.responsesSize; i++) {
log("< [response" + std::to_string(i) + "] " +
linkRawWireless->toHex(result.responses[i]));
}

View File

@@ -2,7 +2,6 @@
#include <libgba-sprite-engine/background/text_stream.h>
#include <tonc.h>
#include <algorithm>
#include <functional>
#include "../../../../lib/LinkWirelessMultiboot.hpp"
@@ -188,8 +187,9 @@ void MultibootScene::processButtons() {
const u8* romToSend =
(const u8*)gbfs_get_obj(fs, ROM_FILE_NAME, &fileLength);
linkWirelessMultiboot->sendRom(romToSend, fileLength, "Multi", "Test", 2,
[]() { return false; });
linkWirelessMultiboot->sendRom(romToSend, fileLength, "Multi", "Test",
0xffff, 2,
[](int connectedPlayers) { return false; });
print();
}

View File

@@ -10,8 +10,8 @@
#include <tonc_core.h>
#include <tonc_math.h>
#include <array>
#include <cstring>
#include <vector> // TODO: ARRAY
#include "LinkGPIO.hpp"
#include "LinkSPI.hpp"
@@ -29,6 +29,7 @@
#define LINK_RAW_WIRELESS_PING_WAIT 50
#define LINK_RAW_WIRELESS_TRANSFER_WAIT 15
#define LINK_RAW_WIRELESS_CMD_TIMEOUT 100
#define LINK_RAW_WIRELESS_MAX_COMMAND_RESPONSE_LENGTH 30
#define LINK_RAW_WIRELESS_MAX_CLIENT_TRANSFER_LENGTH 4
#define LINK_RAW_WIRELESS_MAX_GAME_ID 0x7fff
#define LINK_RAW_WIRELESS_MAX_GAME_NAME_LENGTH 14
@@ -43,7 +44,10 @@
#define LINK_RAW_WIRELESS_BROADCAST_LENGTH 6
#define LINK_RAW_WIRELESS_BROADCAST_RESPONSE_LENGTH \
(1 + LINK_RAW_WIRELESS_BROADCAST_LENGTH)
#define LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH 22
#define LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH 23
#define LINK_RAW_WIRELESS_MAX_SERVERS \
(LINK_RAW_WIRELESS_MAX_COMMAND_RESPONSE_LENGTH / \
LINK_RAW_WIRELESS_BROADCAST_RESPONSE_LENGTH)
#define LINK_RAW_WIRELESS_COMMAND_HELLO 0x10
#define LINK_RAW_WIRELESS_COMMAND_SETUP 0x17
#define LINK_RAW_WIRELESS_COMMAND_BROADCAST 0x16
@@ -85,13 +89,16 @@ class LinkRawWireless {
struct CommandResult {
bool success = false;
std::vector<u32> responses = std::vector<u32>{};
std::array<u32, LINK_RAW_WIRELESS_MAX_COMMAND_RESPONSE_LENGTH> responses =
{};
u32 responsesSize = 0;
};
struct RemoteCommand {
bool success = false;
u8 commandId = 0;
std::vector<u32> params = std::vector<u32>{};
std::array<u32, LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH> params = {};
u32 paramsSize = 0;
};
struct Server {
@@ -111,13 +118,22 @@ class LinkRawWireless {
typedef struct {
u8 nextClientNumber = 0;
std::vector<ConnectedClient> connectedClients = {};
std::array<ConnectedClient, LINK_RAW_WIRELESS_MAX_PLAYERS>
connectedClients = {};
u32 connectedClientsSize = 0;
} SlotStatusResponse;
typedef struct {
std::vector<ConnectedClient> connectedClients = {};
std::array<ConnectedClient, LINK_RAW_WIRELESS_MAX_PLAYERS>
connectedClients = {};
u32 connectedClientsSize = 0;
} AcceptConnectionsResponse;
typedef struct {
std::array<Server, LINK_RAW_WIRELESS_MAX_SERVERS> servers;
u32 serversSize = 0;
} BroadcastReadPollResponse;
enum ConnectionPhase { STILL_CONNECTING, ERROR, SUCCESS };
typedef struct {
@@ -127,7 +143,8 @@ class LinkRawWireless {
typedef struct {
u32 sentBytes[LINK_RAW_WIRELESS_MAX_PLAYERS];
std::vector<u32> data = {};
std::array<u32, LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH> data = {};
u32 dataSize = 0;
} ReceiveDataResponse;
bool isActive() { return isEnabled; }
@@ -155,10 +172,10 @@ class LinkRawWireless {
u32 magic = LINK_RAW_WIRELESS_SETUP_MAGIC) {
return sendCommand(
LINK_RAW_WIRELESS_COMMAND_SETUP,
std::vector<u32>{
(u32)(magic |
(((LINK_RAW_WIRELESS_MAX_PLAYERS - maxPlayers) & 0b11)
<< LINK_RAW_WIRELESS_SETUP_MAX_PLAYERS_BIT))})
{(u32)(magic |
(((LINK_RAW_WIRELESS_MAX_PLAYERS - maxPlayers) & 0b11)
<< LINK_RAW_WIRELESS_SETUP_MAX_PLAYERS_BIT))},
1)
.success;
}
@@ -179,21 +196,22 @@ class LinkRawWireless {
copyName(finalGameName, gameName, LINK_RAW_WIRELESS_MAX_GAME_NAME_LENGTH);
copyName(finalUserName, userName, LINK_RAW_WIRELESS_MAX_USER_NAME_LENGTH);
auto broadcastData = std::vector<u32>{
buildU32(buildU16(finalGameName[1], finalGameName[0]), gameId),
buildU32(buildU16(finalGameName[5], finalGameName[4]),
buildU16(finalGameName[3], finalGameName[2])),
buildU32(buildU16(finalGameName[9], finalGameName[8]),
buildU16(finalGameName[7], finalGameName[6])),
buildU32(buildU16(finalGameName[13], finalGameName[12]),
buildU16(finalGameName[11], finalGameName[10])),
buildU32(buildU16(finalUserName[3], finalUserName[2]),
buildU16(finalUserName[1], finalUserName[0])),
buildU32(buildU16(finalUserName[7], finalUserName[6]),
buildU16(finalUserName[5], finalUserName[4]))};
bool success =
sendCommand(LINK_RAW_WIRELESS_COMMAND_BROADCAST, broadcastData).success;
sendCommand(
LINK_RAW_WIRELESS_COMMAND_BROADCAST,
{buildU32(buildU16(finalGameName[1], finalGameName[0]), gameId),
buildU32(buildU16(finalGameName[5], finalGameName[4]),
buildU16(finalGameName[3], finalGameName[2])),
buildU32(buildU16(finalGameName[9], finalGameName[8]),
buildU16(finalGameName[7], finalGameName[6])),
buildU32(buildU16(finalGameName[13], finalGameName[12]),
buildU16(finalGameName[11], finalGameName[10])),
buildU32(buildU16(finalUserName[3], finalUserName[2]),
buildU16(finalUserName[1], finalUserName[0])),
buildU32(buildU16(finalUserName[7], finalUserName[6]),
buildU16(finalUserName[5], finalUserName[4]))},
LINK_RAW_WIRELESS_BROADCAST_LENGTH)
.success;
if (!success) {
reset();
@@ -226,13 +244,13 @@ class LinkRawWireless {
return false;
}
for (u32 i = 0; i < result.responses.size(); i++) {
for (u32 i = 0; i < result.responsesSize; i++) {
if (i == 0) {
response.nextClientNumber = (u8)lsB32(result.responses[i]);
} else {
response.connectedClients.push_back(
response.connectedClients[response.connectedClientsSize++] =
ConnectedClient{.deviceId = lsB32(result.responses[i]),
.clientNumber = (u8)msB32(result.responses[i])});
.clientNumber = (u8)msB32(result.responses[i])};
}
}
@@ -247,14 +265,14 @@ class LinkRawWireless {
return false;
}
for (u32 i = 0; i < result.responses.size(); i++) {
response.connectedClients.push_back(
for (u32 i = 0; i < result.responsesSize; i++) {
response.connectedClients[response.connectedClientsSize++] =
ConnectedClient{.deviceId = lsB32(result.responses[i]),
.clientNumber = (u8)msB32(result.responses[i])});
.clientNumber = (u8)msB32(result.responses[i])};
}
u8 oldPlayerCount = sessionState.playerCount;
sessionState.playerCount = 1 + result.responses.size();
sessionState.playerCount = 1 + result.responsesSize;
if (sessionState.playerCount != oldPlayerCount)
LRWLOG("now: " + std::to_string(sessionState.playerCount) + " players");
@@ -269,14 +287,14 @@ class LinkRawWireless {
return false;
}
for (u32 i = 0; i < result.responses.size(); i++) {
response.connectedClients.push_back(
for (u32 i = 0; i < result.responsesSize; i++) {
response.connectedClients[response.connectedClientsSize++] =
ConnectedClient{.deviceId = lsB32(result.responses[i]),
.clientNumber = (u8)msB32(result.responses[i])});
.clientNumber = (u8)msB32(result.responses[i])};
}
u8 oldPlayerCount = sessionState.playerCount;
sessionState.playerCount = 1 + result.responses.size();
sessionState.playerCount = 1 + result.responsesSize;
if (sessionState.playerCount != oldPlayerCount)
LRWLOG("now: " + std::to_string(sessionState.playerCount) + " players");
@@ -298,12 +316,11 @@ class LinkRawWireless {
return true;
}
bool broadcastReadPoll(std::vector<Server>& servers) {
bool broadcastReadPoll(BroadcastReadPollResponse response) {
auto result = sendCommand(LINK_RAW_WIRELESS_COMMAND_BROADCAST_READ_POLL);
bool success =
result.success &&
result.responses.size() % LINK_RAW_WIRELESS_BROADCAST_RESPONSE_LENGTH ==
0;
result.responsesSize % LINK_RAW_WIRELESS_BROADCAST_RESPONSE_LENGTH == 0;
if (!success) {
reset();
@@ -311,7 +328,7 @@ class LinkRawWireless {
}
u32 totalBroadcasts =
result.responses.size() / LINK_RAW_WIRELESS_BROADCAST_RESPONSE_LENGTH;
result.responsesSize / LINK_RAW_WIRELESS_BROADCAST_RESPONSE_LENGTH;
for (u32 i = 0; i < totalBroadcasts; i++) {
u32 start = LINK_RAW_WIRELESS_BROADCAST_RESPONSE_LENGTH * i;
@@ -331,7 +348,7 @@ class LinkRawWireless {
server.userName[userI] = '\0';
server.nextClientNumber = (result.responses[start] >> 16) & 0xff;
servers.push_back(server);
response.servers[response.serversSize++] = server;
}
LRWLOG("state = AUTHENTICATED");
@@ -353,9 +370,8 @@ class LinkRawWireless {
}
bool connect(u16 serverId) {
bool success = sendCommand(LINK_RAW_WIRELESS_COMMAND_CONNECT,
std::vector<u32>{serverId})
.success;
bool success =
sendCommand(LINK_RAW_WIRELESS_COMMAND_CONNECT, {serverId}, 1).success;
if (!success) {
reset();
@@ -370,8 +386,8 @@ class LinkRawWireless {
bool keepConnecting(ConnectionStatus& response) {
auto result = sendCommand(LINK_RAW_WIRELESS_COMMAND_IS_FINISHED_CONNECT);
if (!result.success || result.responses.size() == 0) {
if (result.responses.size() == 0)
if (!result.success || result.responsesSize == 0) {
if (result.responsesSize == 0)
LRWLOG("! empty response");
reset();
return false;
@@ -398,8 +414,8 @@ class LinkRawWireless {
bool finishConnection() {
auto result = sendCommand(LINK_RAW_WIRELESS_COMMAND_FINISH_CONNECTION);
if (!result.success || result.responses.size() == 0) {
if (result.responses.size() == 0)
if (!result.success || result.responsesSize == 0) {
if (result.responsesSize == 0)
LRWLOG("! empty response");
reset();
return false;
@@ -420,16 +436,23 @@ class LinkRawWireless {
return true;
}
bool sendData(std::vector<u32> data, u32 _bytes = 0) {
u32 bytes = _bytes == 0 ? data.size() * 4 : _bytes;
bool sendData(
std::array<u32, LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH> data,
u32 dataSize,
u32 _bytes = 0) {
u32 bytes = _bytes == 0 ? dataSize * 4 : _bytes;
u32 header = sessionState.currentPlayerId == 0
? bytes
: (bytes << (3 + sessionState.currentPlayerId * 5));
data.insert(data.begin(), header);
for (u32 i = dataSize; i > 0; i--)
data[i] = data[i - 1];
data[0] = header;
dataSize++;
LRWLOG("using header " + toHex(header));
bool success =
sendCommand(LINK_RAW_WIRELESS_COMMAND_SEND_DATA, data).success;
sendCommand(LINK_RAW_WIRELESS_COMMAND_SEND_DATA, data, dataSize)
.success;
if (!success) {
reset();
@@ -439,17 +462,23 @@ class LinkRawWireless {
return true;
}
bool sendDataAndWait(std::vector<u32> data,
RemoteCommand& remoteCommand,
u32 _bytes = 0) {
u32 bytes = _bytes == 0 ? data.size() * 4 : _bytes;
bool sendDataAndWait(
std::array<u32, LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH> data,
u32 dataSize,
RemoteCommand& remoteCommand,
u32 _bytes = 0) {
u32 bytes = _bytes == 0 ? dataSize * 4 : _bytes;
u32 header = sessionState.currentPlayerId == 0
? bytes
: (bytes << (3 + sessionState.currentPlayerId * 5));
data.insert(data.begin(), header);
for (u32 i = dataSize; i > 0; i--)
data[i] = data[i - 1];
data[0] = header;
dataSize++;
LRWLOG("using header " + toHex(header));
if (!sendCommand(LINK_RAW_WIRELESS_COMMAND_SEND_DATA_AND_WAIT, data)
if (!sendCommand(LINK_RAW_WIRELESS_COMMAND_SEND_DATA_AND_WAIT, data,
dataSize)
.success) {
reset();
return false;
@@ -462,7 +491,9 @@ class LinkRawWireless {
bool receiveData(ReceiveDataResponse& response) {
auto result = sendCommand(LINK_RAW_WIRELESS_COMMAND_RECEIVE_DATA);
response.data = result.responses;
for (u32 i = 0; i < result.responsesSize; i++)
response.data[i] = result.responses[i];
response.dataSize = result.responsesSize;
if (!result.success) {
reset();
@@ -472,9 +503,11 @@ class LinkRawWireless {
for (u32 i = 0; i < LINK_RAW_WIRELESS_MAX_PLAYERS; i++)
response.sentBytes[i] = 0;
if (response.data.size() > 0) {
if (response.dataSize > 0) {
u32 header = response.data[0];
response.data.erase(response.data.begin());
for (u32 i = 1; i < response.dataSize; i++)
response.data[i - 1] = response.data[i];
response.dataSize--;
response.sentBytes[0] = header & 0b1111111;
response.sentBytes[1] = (header >> 8) & 0b11111;
response.sentBytes[2] = (header >> 13) & 0b11111;
@@ -496,10 +529,12 @@ class LinkRawWireless {
return remoteCommand.success;
}
CommandResult sendCommand(u8 type,
std::vector<u32> params = std::vector<u32>{}) {
CommandResult sendCommand(
u8 type,
std::array<u32, LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH> params =
{},
u16 length = 0) {
CommandResult result;
u16 length = params.size();
u32 command = buildCommand(type, length);
u32 r;
@@ -510,7 +545,8 @@ class LinkRawWireless {
}
u32 parameterCount = 0;
for (auto& param : params) {
for (u32 i = 0; i < length; i++) {
u32 param = params[i];
LRWLOG("sending param" + std::to_string(parameterCount) + ": 0x" +
toHex(param));
if ((r = transfer(param)) != LINK_RAW_WIRELESS_DATA_REQUEST) {
@@ -551,7 +587,7 @@ class LinkRawWireless {
LRWLOG("response " + std::to_string(i + 1) + "/" +
std::to_string(responses) + ":");
u32 responseData = transfer(LINK_RAW_WIRELESS_DATA_REQUEST);
result.responses.push_back(responseData);
result.responses[result.responsesSize++] = responseData;
LRWLOG("<< " + toHex(responseData));
}
@@ -596,7 +632,7 @@ class LinkRawWireless {
reset();
return remoteCommand;
}
remoteCommand.params.push_back(paramData);
remoteCommand.params[remoteCommand.paramsSize++] = paramData;
LRWLOG("<< " + toHex(paramData));
}

View File

@@ -39,6 +39,9 @@
#define LINK_WIRELESS_MULTIBOOT_MAX_PLAYERS 5
#define LINK_WIRELESS_MULTIBOOT_HEADER_SIZE 0xC0
#define LINK_WIRELESS_MULTIBOOT_SETUP_MAGIC 0x003F0120
#define LINK_WIRELESS_MULTIBOOT_GAME_ID_MULTIBOOT_FLAG 0b1000000000000000
#define LINK_WIRELESS_MULTIBOOT_FRAME_LINES 228
#define LINK_WIRELESS_MULTIBOOT_FRAMES_BEFORE_HANDSHAKE 20 // ~300ms
static volatile char LINK_WIRELESS_MULTIBOOT_VERSION[] =
"LinkWirelessMultiboot/v6.2.0";
@@ -88,6 +91,7 @@ class LinkWirelessMultiboot {
u32 romSize,
const char* gameName,
const char* userName,
const u16 gameId,
u8 players,
F cancel) {
if (romSize < LINK_WIRELESS_MULTIBOOT_MIN_ROM_SIZE)
@@ -98,49 +102,33 @@ class LinkWirelessMultiboot {
players > LINK_WIRELESS_MULTIBOOT_MAX_PLAYERS)
return INVALID_PLAYERS;
if (!link->activate()) {
LWMLOG("! adapter not detected");
if (!activate())
return ADAPTER_NOT_DETECTED;
}
LWMLOG("activated");
if (!link->setup(players, LINK_WIRELESS_MULTIBOOT_SETUP_MAGIC)) {
LWMLOG("! setup failed");
if (!initialize(gameName, userName, gameId, players))
return FAILURE;
}
LWMLOG("setup ok");
bool success; // TODO: REMOVE
success = link->broadcast("Multi", "Test", 0b1111111111111111);
if (!success) {
LWMLOG("broadcast failed");
return FAILURE;
}
LWMLOG("broadcast set");
success = link->startHost();
if (!success) {
LWMLOG("start host failed");
return FAILURE;
}
LWMLOG("host started");
LinkRawWireless::AcceptConnectionsResponse acceptResponse;
while (link->playerCount() == 1) {
while (link->playerCount() < players) {
link->acceptConnections(acceptResponse);
if (cancel(players)) {
link->deactivate();
return CANCELED;
}
}
LWMLOG("connected!");
linkRawWireless->wait(228 * 20); // ~300ms
LWMLOG("connected!"); // TODO: MOVE HANDSHAKE TO WHILE
linkRawWireless->wait(LINK_WIRELESS_MULTIBOOT_FRAME_LINES *
LINK_WIRELESS_MULTIBOOT_FRAMES_BEFORE_HANDSHAKE);
// HANDSHAKE
bool hasData = false;
LinkRawWireless::ReceiveDataResponse response;
while (!hasData) {
if (!sendAndExpectData(std::vector<u32>{}, 1, response))
if (!sendAndExpectData(toArray(), 0, 1, response))
return FAILURE;
hasData = response.data.size() > 0;
hasData = response.dataSize > 0;
}
LWMLOG("data received");
@@ -157,10 +145,10 @@ class LinkWirelessMultiboot {
serverHeader = createACKFor(clientHeader);
u32 sndHeader = serializeServerHeader(serverHeader);
if (!sendAndExpectData(std::vector<u32>{sndHeader}, 3, response))
if (!sendAndExpectData(toArray(sndHeader), 1, 3, response))
return FAILURE;
if (response.data.size() == 0) {
if (response.dataSize == 0) {
goto firstack;
}
clientHeader = parseClientHeader(response.data[0]);
@@ -177,10 +165,10 @@ class LinkWirelessMultiboot {
secondack:
serverHeader = createACKFor(clientHeader);
sndHeader = serializeServerHeader(serverHeader);
if (!sendAndExpectData(std::vector<u32>{sndHeader}, 3, response))
if (!sendAndExpectData(toArray(sndHeader), 1, 3, response))
return FAILURE;
if (response.data.size() == 0) {
if (response.dataSize == 0) {
goto secondack;
}
clientHeader = parseClientHeader(response.data[0]);
@@ -198,7 +186,7 @@ class LinkWirelessMultiboot {
link->wait(228);
serverHeader = createACKFor(clientHeader);
sndHeader = serializeServerHeader(serverHeader);
if (!sendAndExpectData(std::vector<u32>{sndHeader}, 3, response))
if (!sendAndExpectData(toArray(sndHeader), 1, 3, response))
return FAILURE;
clientHeader = parseClientHeader(response.data[0]);
@@ -218,8 +206,7 @@ class LinkWirelessMultiboot {
serverHeader.phase = 0;
serverHeader.slotState = 1;
sndHeader = serializeServerHeader(serverHeader);
if (!sendAndExpectData(std::vector<u32>{sndHeader, 0x54, 0x02}, 10,
response))
if (!sendAndExpectData(toArray(sndHeader, 0x54, 0x02), 3, 10, response))
return FAILURE;
clientHeader = parseClientHeader(response.data[0]);
if (clientHeader.isACK == 1 && clientHeader.n == 1 &&
@@ -233,10 +220,10 @@ class LinkWirelessMultiboot {
u32 transferredBytes = 0;
u32 n = 1;
u32 phase = 0;
bool isRetry = false;
// bool isRetry = false;
u32 progress = 0;
while (transferredBytes < romSize) {
isRetry = false;
// isRetry = false;
retry:
serverHeader.isACK = 0;
serverHeader.targetSlots = 0b0001; // TODO: Implement
@@ -245,8 +232,9 @@ class LinkWirelessMultiboot {
serverHeader.phase = phase;
serverHeader.slotState = 2;
sndHeader = serializeServerHeader(serverHeader);
std::vector<u32> data;
data.push_back(sndHeader | (rom[transferredBytes] << 24));
std::array<u32, LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH> data;
u32 dataSize = 0;
data[dataSize++] = sndHeader | (rom[transferredBytes] << 24);
// if (!isRetry)
// bytes.push_back(rom[transferredBytes]);
for (u32 i = 1; i < 84; i += 4) {
@@ -259,15 +247,15 @@ class LinkWirelessMultiboot {
// bytes.push_back(byte);
}
}
data.push_back(d);
data[dataSize++] = d;
}
LinkRawWireless::ReceiveDataResponse response;
if (!sendAndExpectData(data, 87, response)) {
if (!sendAndExpectData(data, 22, 87, response)) {
LWMLOG("SendData failed!");
return FAILURE;
}
if (response.data.size() == 0) {
isRetry = true;
if (response.dataSize == 0) {
// isRetry = true;
goto retry;
}
@@ -288,7 +276,7 @@ class LinkWirelessMultiboot {
LWMLOG("-> " + std::to_string(transferredBytes * 100 / romSize));
}
} else {
isRetry = true;
// isRetry = true;
goto retry;
}
}
@@ -307,7 +295,7 @@ class LinkWirelessMultiboot {
serverHeader.phase = 0;
serverHeader.slotState = 3;
sndHeader = serializeServerHeader(serverHeader);
if (!sendAndExpectData(std::vector<u32>{sndHeader}, 3, response))
if (!sendAndExpectData(toArray(sndHeader), 1, 3, response))
return FAILURE;
clientHeader = parseClientHeader(response.data[0]);
if (clientHeader.isACK == 1 && clientHeader.n == 0 &&
@@ -329,7 +317,7 @@ class LinkWirelessMultiboot {
serverHeader.phase = 0;
serverHeader.slotState = 0;
sndHeader = serializeServerHeader(serverHeader);
if (!sendAndExpectData(std::vector<u32>{sndHeader}, 3, response))
if (!sendAndExpectData(toArray(sndHeader), 1, 3, response))
return FAILURE;
clientHeader = parseClientHeader(response.data[0]);
// if (clientHeader.slotState == 0)
@@ -362,12 +350,51 @@ class LinkWirelessMultiboot {
ClientSDKHeader lastACK;
private:
bool sendAndExpectData(std::vector<u32> data,
u32 _bytes,
LinkRawWireless::ReceiveDataResponse& response) {
bool activate() {
if (!link->activate()) {
LWMLOG("! adapter not detected");
return false;
}
LWMLOG("activated");
return true;
}
bool initialize(const char* gameName,
const char* userName,
const u16 gameId,
u8 players) {
if (!link->setup(players, LINK_WIRELESS_MULTIBOOT_SETUP_MAGIC)) {
LWMLOG("! setup failed");
return false;
}
LWMLOG("setup ok");
if (!link->broadcast(
gameName, userName,
gameId | LINK_WIRELESS_MULTIBOOT_GAME_ID_MULTIBOOT_FLAG)) {
LWMLOG("! broadcast failed");
return false;
}
LWMLOG("broadcast data set");
if (!link->startHost()) {
LWMLOG("! start host failed");
return false;
}
LWMLOG("host started");
return true;
}
bool sendAndExpectData(
std::array<u32, LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH> data,
u32 dataSize,
u32 _bytes,
LinkRawWireless::ReceiveDataResponse& response) {
LinkRawWireless::RemoteCommand remoteCommand;
bool success = false;
success = link->sendDataAndWait(data, remoteCommand, _bytes);
success = link->sendDataAndWait(data, dataSize, remoteCommand, _bytes);
if (!success) {
LWMLOG("senddatawait no");
return false;
@@ -408,6 +435,12 @@ class LinkWirelessMultiboot {
serverSerializer.asStruct = serverHeader;
return serverSerializer.asInt & 0xffffff;
}
template <typename... Args>
std::array<u32, LINK_RAW_WIRELESS_MAX_COMMAND_TRANSFER_LENGTH> toArray(
Args... args) {
return {static_cast<u32>(args)...};
}
};
extern LinkWirelessMultiboot* linkWirelessMultiboot;