From 65841b3cb218b06da8a71144ca2520e06248984e Mon Sep 17 00:00:00 2001 From: Rodrigo Alfonso Date: Mon, 27 Jan 2025 03:32:23 -0300 Subject: [PATCH] Replacing LINK_WIRELESS_MULTIBOOT_ASYNC_LIMIT_TRANSFER_SPEED with sendRom(...) parameter --- README.md | 3 +- lib/LinkWirelessMultiboot.hpp | 35 ++++++++++------------ lib/c_bindings/C_LinkWirelessMultiboot.cpp | 5 ++-- lib/c_bindings/C_LinkWirelessMultiboot.h | 3 +- 4 files changed, 22 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 33d79e2..07e7aeb 100644 --- a/README.md +++ b/README.md @@ -331,14 +331,13 @@ This version (`LinkWirelessMultiboot::Async`) allows more advanced use cases lik ### Compile-time constants - `LINK_WIRELESS_MULTIBOOT_ENABLE_LOGGING`: to enable logging. Set `linkWirelessMultibootAsync->logger` and it will be called to report the detailed state of the library. Note that this option `#include`s `std::string`! -- `LINK_WIRELESS_MULTIBOOT_ASYNC_LIMIT_TRANSFER_SPEED`: to only send one ROM chunk per frame. This slows down transfers but can help fix audio popping issues, as it reduces CPU time spent in interrupt handlers. - `LINK_WIRELESS_MULTIBOOT_ASYNC_DISABLE_NESTED_IRQ`: to disable nested IRQs. In the async version, SERIAL IRQs can be interrupted (once they clear their time-critical needs) by default, which helps prevent issues with audio engines. However, if something goes wrong, you can disable this behavior. ### Methods | Name | Return type | Description | | --------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `sendRom(rom, romSize, gameName, userName, gameId, players, [waitForReadySignal], [keepConnectionAlive])` | **bool** | Sends the `rom`.

The `players` must be the number of consoles that will download the ROM. Once this number of players is reached, the code will start transmitting the ROM bytes.

The `romSize` must be a number between `448` and `262144`. It's recommended to use a ROM size that is a multiple of `16`, since this also ensures compatibility with Multiboot via Link Cable.

If `waitForReadySignal` is `true`, it will wait until the `markReady()` method is called to start the transfer.

Once completed, `getState()` should return `LinkWirelessMultiboot::Async::State::STOPPED` and `getResult()` should return `LinkWirelessMultiboot::Async::Result::SUCCESS`.

Returns `false` if there's a pending transfer or the data is invalid.

If `keepConnectionAlive` is `true`, the adapter won't be reset after a successful transfer, so users can continue the session using `LinkWireless::restoreExistingConnection()`. | +| `sendRom(rom, romSize, gameName, userName, gameId, players, [waitForReadySignal], [keepConnectionAlive], [maxTransfersPerFrame])` | **bool** | Sends the `rom`.

The `players` must be the number of consoles that will download the ROM. Once this number of players is reached, the code will start transmitting the ROM bytes.

The `romSize` must be a number between `448` and `262144`. It's recommended to use a ROM size that is a multiple of `16`, since this also ensures compatibility with Multiboot via Link Cable.

If `waitForReadySignal` is `true`, it will wait until the `markReady()` method is called to start the transfer.

Setting a `maxTransfersPerFrame` limit slows down transfers but can help fix audio popping issues, as it reduces CPU time spent in interrupt handlers.

Once completed, `getState()` should return `LinkWirelessMultiboot::Async::State::STOPPED` and `getResult()` should return `LinkWirelessMultiboot::Async::Result::SUCCESS`.

Returns `false` if there's a pending transfer or the data is invalid.

If `keepConnectionAlive` is `true`, the adapter won't be reset after a successful transfer, so users can continue the session using `LinkWireless::restoreExistingConnection()`. | | `reset()` | **bool** | Turns off the adapter and deactivates the library, canceling the in-progress transfer, if any. It returns a boolean indicating whether the transition to low consumption mode was successful. | | `getState()` | **LinkWirelessMultiboot::Async::State** | Returns the current state. | | `getResult([clear])` | **LinkWirelessMultiboot::Async::Result** | Returns the result of the last operation.

After this call, the result is cleared if `clear` is `true` (default behavior). | diff --git a/lib/LinkWirelessMultiboot.hpp b/lib/LinkWirelessMultiboot.hpp index 30fe8d3..8bbaf44 100644 --- a/lib/LinkWirelessMultiboot.hpp +++ b/lib/LinkWirelessMultiboot.hpp @@ -64,16 +64,6 @@ // #define LINK_WIRELESS_MULTIBOOT_ENABLE_LOGGING #endif -#ifndef LINK_WIRELESS_MULTIBOOT_ASYNC_LIMIT_TRANSFER_SPEED -/** - * @brief Limit transfer speed (uncomment to enable). - * In the async version, enable this option to only send one ROM chunk per - * frame. This slows down transfers but can help fix audio popping - * issues, as it reduces CPU time spent in interrupt handlers. - */ -// #define LINK_WIRELESS_MULTIBOOT_ASYNC_LIMIT_TRANSFER_SPEED -#endif - #ifndef LINK_WIRELESS_MULTIBOOT_ASYNC_DISABLE_NESTED_IRQ /** * @brief Disable nested IRQs (uncomment to enable). @@ -748,6 +738,9 @@ class LinkWirelessMultiboot { * @param keepConnectionAlive If `true`, the adapter won't be reset after * a successful transfer, so users can continue the session using * `LinkWireless::restoreExistingConnection()`. + * @param maxTransfersPerFrame Transfer limit per frame. This slows down + * transfers but can help fix audio popping issues, as it reduces CPU time + * spent in interrupt handlers. */ bool sendRom(const u8* rom, u32 romSize, @@ -756,7 +749,8 @@ class LinkWirelessMultiboot { const u16 gameId, u8 players, bool waitForReadySignal = false, - bool keepConnectionAlive = false) { + bool keepConnectionAlive = false, + u32 maxTransfersPerFrame = 0xffffffff) { if (state != State::STOPPED) return false; @@ -781,6 +775,7 @@ class LinkWirelessMultiboot { fixedData.players = players; fixedData.waitForReadySignal = waitForReadySignal; fixedData.keepConnectionAlive = keepConnectionAlive; + fixedData.maxTransfersPerFrame = maxTransfersPerFrame; generateFirstPagePatch(rom, fixedData.firstPagePatch); _LWMLOG_("starting..."); @@ -908,6 +903,7 @@ class LinkWirelessMultiboot { u8 players = 0; bool waitForReadySignal = false; bool keepConnectionAlive = false; + u32 maxTransfersPerFrame = 0xffffffff; u8 firstPagePatch[LinkWirelessOpenSDK::MAX_PAYLOAD_SERVER] = {}; }; @@ -920,6 +916,7 @@ class LinkWirelessMultiboot { struct MultibootDynamicData { u32 irqTimeout = 0; u32 wait = 0; + u32 frameTransfers = 0; u8 currentClient = 0; HandshakeClientData handshakeClient = HandshakeClientData{}; @@ -946,6 +943,7 @@ class LinkWirelessMultiboot { #endif void processNewFrame() { + dynamicData.frameTransfers = 0; dynamicData.irqTimeout++; if (dynamicData.irqTimeout >= MAX_IRQ_TIMEOUT_FRAMES) { #ifndef LINK_WIRELESS_MULTIBOOT_ASYNC_DISABLE_NESTED_IRQ @@ -964,13 +962,11 @@ class LinkWirelessMultiboot { } break; } -#ifdef LINK_WIRELESS_MULTIBOOT_ASYNC_LIMIT_TRANSFER_SPEED case State::RESTING: { state = State::ENSURING_CLIENTS_ALIVE; checkClientsAlive(); break; } -#endif default: { } } @@ -1183,12 +1179,13 @@ class LinkWirelessMultiboot { _LWMLOG_("-> " + std::to_string(newPercentage)); } -#ifdef LINK_WIRELESS_MULTIBOOT_ASYNC_LIMIT_TRANSFER_SPEED - state = State::RESTING; -#else - state = State::ENSURING_CLIENTS_ALIVE; - checkClientsAlive(); -#endif + dynamicData.frameTransfers++; + if (dynamicData.frameTransfers < fixedData.maxTransfersPerFrame) { + state = State::ENSURING_CLIENTS_ALIVE; + checkClientsAlive(); + } else { + state = State::RESTING; + } break; } case State::CONFIRMING_STEP1: { diff --git a/lib/c_bindings/C_LinkWirelessMultiboot.cpp b/lib/c_bindings/C_LinkWirelessMultiboot.cpp index 25e8b43..7731842 100644 --- a/lib/c_bindings/C_LinkWirelessMultiboot.cpp +++ b/lib/c_bindings/C_LinkWirelessMultiboot.cpp @@ -58,10 +58,11 @@ bool C_LinkWirelessMultiboot_Async_sendRom(C_LinkWirelessMultibootHandle handle, u16 gameId, u8 players, bool waitForReadySignal, - bool keepConnectionAlive) { + bool keepConnectionAlive, + u32 maxTransfersPerFrame) { return static_cast(handle)->sendRom( rom, romSize, gameName, userName, gameId, players, waitForReadySignal, - keepConnectionAlive); + keepConnectionAlive, maxTransfersPerFrame); } bool C_LinkWirelessMultiboot_Async_reset( diff --git a/lib/c_bindings/C_LinkWirelessMultiboot.h b/lib/c_bindings/C_LinkWirelessMultiboot.h index f0058f5..02263c7 100644 --- a/lib/c_bindings/C_LinkWirelessMultiboot.h +++ b/lib/c_bindings/C_LinkWirelessMultiboot.h @@ -105,7 +105,8 @@ bool C_LinkWirelessMultiboot_Async_sendRom(C_LinkWirelessMultibootHandle handle, u16 gameId, u8 players, bool waitForReadySignal, - bool keepConnectionAlive); + bool keepConnectionAlive, + u32 maxTransfersPerFrame); bool C_LinkWirelessMultiboot_Async_reset( C_LinkWirelessMultiboot_AsyncHandle handle);