LinkRawWireless: Implementing SystemStatus command (0x13)

This commit is contained in:
Rodrigo Alfonso 2025-01-03 12:19:44 -03:00
parent f9e0e1dd63
commit 9b41cf30df
7 changed files with 114 additions and 6 deletions

View File

@ -450,7 +450,8 @@ Both Pokemon games and the multiboot ROM that the adapter sends when no cartridg
* Bits `16-23`: A 4-bit array with slots. If the console is a client, it'll have a 1 in the position assigned to that slot (e.g. the one with `clientNumber` 3 will have `0100`). The host will always have `0000` here.
* Bits `24-31`: A number indicating the state of the adapter
- `0` = idle
- `1`/`2` = serving (host)
- `1` = serving (host), closed server
- `2` = serving (host), open server
- `3` = searching
- `4` = connecting
- `5` = connected (client)

View File

@ -1,3 +1,5 @@
#define LINK_RAW_WIRELESS_ENABLE_LOGGING
#include "../../../lib/LinkRawWireless.hpp"
#include <libgba-sprite-engine/gba_engine.h>

View File

@ -1,3 +1,5 @@
#define LINK_RAW_WIRELESS_ENABLE_LOGGING
#include "../../../../lib/LinkRawWireless.hpp"
#include "DebugScene.h"
@ -218,11 +220,11 @@ void DebugScene::addCommandMenuOptions() {
commandMenuOptions.push_back(
CommandMenuOption{.name = "0x1b (EndHost)", .command = 0x1b});
commandMenuOptions.push_back(
CommandMenuOption{.name = "0x1c (BroadcastRead1)", .command = 0x1c});
CommandMenuOption{.name = "0x1c (BroadcastReadStart)", .command = 0x1c});
commandMenuOptions.push_back(
CommandMenuOption{.name = "0x1d (BroadcastRead2)", .command = 0x1d});
CommandMenuOption{.name = "0x1d (BroadcastReadPoll)", .command = 0x1d});
commandMenuOptions.push_back(
CommandMenuOption{.name = "0x1e (BroadcastRead3)", .command = 0x1e});
CommandMenuOption{.name = "0x1e (BroadcastReadEnd)", .command = 0x1e});
commandMenuOptions.push_back(
CommandMenuOption{.name = "0x1f (Connect)", .command = 0x1f});
commandMenuOptions.push_back(
@ -472,8 +474,22 @@ void DebugScene::processCommand(u32 selectedCommandIndex) {
case 0x10:
case 0x11:
case 0x12:
case 0x13:
goto simple;
case 0x13: {
return logOperation("sending " + name, []() {
LinkRawWireless::SystemStatusResponse response;
bool success = linkRawWireless->getSystemStatus(response);
if (success) {
log("< [device id] " + linkRawWireless->toHex(response.deviceId, 4));
log("< [player id] " + std::to_string(response.currentPlayerId));
log("< [state] " + std::to_string(response.adapterState));
log("< [closed] " + std::to_string(response.isServerClosed));
}
return success;
});
}
case 0x14: {
return logOperation("sending " + name, []() {
LinkRawWireless::SlotStatusResponse response;

View File

@ -63,7 +63,7 @@ compile() {
# LinkRawWireless_demo
cd LinkRawWireless_demo/
make rebuild $args USERFLAGS="-DLINK_RAW_WIRELESS_ENABLE_LOGGING=1"
make rebuild $args
cp LinkRawWireless_demo$suffix.gba ../$folder/
cd ..

View File

@ -70,6 +70,7 @@ class LinkRawWireless {
static constexpr int COMMAND_SETUP = 0x17;
static constexpr int COMMAND_BROADCAST = 0x16;
static constexpr int COMMAND_START_HOST = 0x19;
static constexpr int COMMAND_SYSTEM_STATUS = 0x13;
static constexpr int COMMAND_SLOT_STATUS = 0x14;
static constexpr int COMMAND_ACCEPT_CONNECTIONS = 0x1a;
static constexpr int COMMAND_END_HOST = 0x1b;
@ -133,6 +134,13 @@ class LinkRawWireless {
u8 clientNumber = 0;
};
struct SystemStatusResponse {
u16 deviceId = 0;
u8 currentPlayerId = 0;
State adapterState = AUTHENTICATED;
bool isServerClosed = false;
};
struct SlotStatusResponse {
u8 nextClientNumber = 0;
std::array<ConnectedClient, LINK_RAW_WIRELESS_MAX_PLAYERS>
@ -282,6 +290,62 @@ class LinkRawWireless {
return true;
}
/**
* @brief Calls the SystemStatus (`0x13`) command.
* @param response A structure that will be filled with the response data.
*/
bool getSystemStatus(SystemStatusResponse& response) {
auto result = sendCommand(COMMAND_SYSTEM_STATUS);
if (!result.success || result.responsesSize != 1) {
reset();
return false;
}
u32 status = result.responses[0];
response.deviceId = lsB32(status);
u8 slot = lsB16(msB32(status)) & 0b1111;
response.currentPlayerId = slot == 0b0001 ? 1
: slot == 0b0010 ? 2
: slot == 0b0100 ? 3
: slot == 0b1000 ? 4
: 0;
u8 adapterState = msB16(msB32(status));
response.isServerClosed = false;
switch (adapterState) {
case 1: {
response.adapterState = State::SERVING;
response.isServerClosed = true;
break;
}
case 2: {
response.adapterState = State::SERVING;
break;
}
case 3: {
response.adapterState = State::SEARCHING;
break;
}
case 4: {
response.adapterState = State::CONNECTING;
break;
}
case 5: {
response.adapterState = State::CONNECTED;
break;
}
default: {
response.adapterState = State::AUTHENTICATED;
break;
}
}
return true;
}
/**
* @brief Calls the SlotStatus (`0x14`) command.
* @param response A structure that will be filled with the response data.

View File

@ -43,6 +43,21 @@ bool C_LinkRawWireless_startHost(C_LinkRawWirelessHandle handle) {
return static_cast<LinkRawWireless*>(handle)->startHost();
}
bool C_LinkRawWireless_getSystemStatus(
C_LinkRawWirelessHandle handle,
C_LinkRawWireless_SystemStatusResponse* response) {
LinkRawWireless::SystemStatusResponse nativeResponse;
bool success =
static_cast<LinkRawWireless*>(handle)->getSystemStatus(nativeResponse);
response->deviceId = nativeResponse.deviceId;
response->currentPlayerId = nativeResponse.currentPlayerId;
response->adapterState =
static_cast<C_LinkRawWireless_State>(nativeResponse.adapterState);
response->isServerClosed = nativeResponse.isServerClosed;
return success;
}
bool C_LinkRawWireless_getSlotStatus(
C_LinkRawWirelessHandle handle,
C_LinkRawWireless_SlotStatusResponse* response) {

View File

@ -55,6 +55,13 @@ typedef struct {
u8 clientNumber;
} C_LinkRawWireless_ConnectedClient;
typedef struct {
u16 deviceId;
u8 currentPlayerId;
C_LinkRawWireless_State adapterState;
bool isServerClosed;
} C_LinkRawWireless_SystemStatusResponse;
typedef struct {
u8 nextClientNumber;
C_LinkRawWireless_ConnectedClient
@ -107,6 +114,9 @@ bool C_LinkRawWireless_broadcast(C_LinkRawWirelessHandle handle,
const char* userName,
u16 gameId);
bool C_LinkRawWireless_startHost(C_LinkRawWirelessHandle handle);
bool C_LinkRawWireless_getSystemStatus(
C_LinkRawWirelessHandle handle,
C_LinkRawWireless_SystemStatusResponse* response);
bool C_LinkRawWireless_getSlotStatus(
C_LinkRawWirelessHandle handle,
C_LinkRawWireless_SlotStatusResponse* response);