From f10ad006ae07acc8222cb124ae7fbf6aa2b2dd16 Mon Sep 17 00:00:00 2001 From: Rodrigo Alfonso Date: Tue, 30 Jan 2024 09:01:46 -0300 Subject: [PATCH] Migrating LinkRawWireless to static arrays --- .../src/scenes/DebugScene.cpp | 44 +++-- .../src/scenes/MultibootScene.cpp | 6 +- lib/LinkRawWireless.hpp | 170 +++++++++++------- lib/LinkWirelessMultiboot.hpp | 133 ++++++++------ 4 files changed, 216 insertions(+), 137 deletions(-) diff --git a/examples/LinkRawWireless_demo/src/scenes/DebugScene.cpp b/examples/LinkRawWireless_demo/src/scenes/DebugScene.cpp index a80443b..76b75ea 100644 --- a/examples/LinkRawWireless_demo/src/scenes/DebugScene.cpp +++ b/examples/LinkRawWireless_demo/src/scenes/DebugScene.cpp @@ -111,6 +111,14 @@ void log(std::string string) { scrollPageDown(); } +std::array toArray( + std::vector vector) { + std::array array; + for (u32 i = 0; i < vector.size(); i++) + array[i] = vector[i]; + return array; +} + std::vector 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 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 params) { logOperation("sending " + name, [id, ¶ms]() { - 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])); } diff --git a/examples/LinkWirelessMultiboot_demo/src/scenes/MultibootScene.cpp b/examples/LinkWirelessMultiboot_demo/src/scenes/MultibootScene.cpp index 68ea64b..7baeb6e 100644 --- a/examples/LinkWirelessMultiboot_demo/src/scenes/MultibootScene.cpp +++ b/examples/LinkWirelessMultiboot_demo/src/scenes/MultibootScene.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #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(); } diff --git a/lib/LinkRawWireless.hpp b/lib/LinkRawWireless.hpp index 1751ec0..bc842a7 100644 --- a/lib/LinkRawWireless.hpp +++ b/lib/LinkRawWireless.hpp @@ -10,8 +10,8 @@ #include #include +#include #include -#include // 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 responses = std::vector{}; + std::array responses = + {}; + u32 responsesSize = 0; }; struct RemoteCommand { bool success = false; u8 commandId = 0; - std::vector params = std::vector{}; + std::array params = {}; + u32 paramsSize = 0; }; struct Server { @@ -111,13 +118,22 @@ class LinkRawWireless { typedef struct { u8 nextClientNumber = 0; - std::vector connectedClients = {}; + std::array + connectedClients = {}; + u32 connectedClientsSize = 0; } SlotStatusResponse; typedef struct { - std::vector connectedClients = {}; + std::array + connectedClients = {}; + u32 connectedClientsSize = 0; } AcceptConnectionsResponse; + typedef struct { + std::array 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 data = {}; + std::array 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)(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{ - 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& 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{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 data, u32 _bytes = 0) { - u32 bytes = _bytes == 0 ? data.size() * 4 : _bytes; + bool sendData( + std::array 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 data, - RemoteCommand& remoteCommand, - u32 _bytes = 0) { - u32 bytes = _bytes == 0 ? data.size() * 4 : _bytes; + bool sendDataAndWait( + std::array 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 params = std::vector{}) { + CommandResult sendCommand( + u8 type, + std::array 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)); } diff --git a/lib/LinkWirelessMultiboot.hpp b/lib/LinkWirelessMultiboot.hpp index ea1140d..c4accae 100644 --- a/lib/LinkWirelessMultiboot.hpp +++ b/lib/LinkWirelessMultiboot.hpp @@ -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{}, 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{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{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{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{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 data; - data.push_back(sndHeader | (rom[transferredBytes] << 24)); + std::array 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{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{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 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 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 + std::array toArray( + Args... args) { + return {static_cast(args)...}; + } }; extern LinkWirelessMultiboot* linkWirelessMultiboot;