mirror of
https://github.com/afska/gba-link-connection.git
synced 2026-10-02 05:47:11 -05:00
Migrating LinkRawWireless to static arrays
This commit is contained in:
@@ -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, ¶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]));
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user