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);