diff --git a/README.md b/README.md index cf1601b..a977b97 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,12 @@ A set of Game Boy Advance (GBA) C++ libraries to interact with the Serial Port. Its main purpose is to provide multiplayer support to homebrew games. -- [๐Ÿ‘พ](#-LinkCable) [LinkCable.h](lib/LinkCable.h): The classic 16-bit **Multi-Play mode** (up to 4 players) using a GBA Link Cable! -- [๐Ÿ’ป](#-LinkCableMultiboot) [LinkCableMultiboot.h](lib/LinkCableMultiboot.h): โ€Send **Multiboot software** (small 256KiB ROMs) to other GBAs with no cartridge! -- [๐Ÿ”Œ](#-LinkGPIO) [LinkGPIO.h](lib/LinkGPIO.h): Use the Link Port however you want to control **any device** (like LEDs, rumble motors, and that kind of stuff)! -- [๐Ÿ”—](#-LinkSPI) [LinkSPI.h](lib/LinkSPI.h): Connect with a PC (like a **Raspberry Pi**) or another GBA (with a GBC Link Cable) using this mode. Transfer up to 2Mbit/s! -- [๐Ÿ“ป](#-LinkWireless) [LinkWireless.h](lib/LinkWireless.h): Connect up to 5 consoles with the **Wireless Adapter**! -- [๐ŸŒŽ](#-LinkUniversal) [LinkUniversal.h](lib/LinkUniversal.h): Add multiplayer support to your game, both with ๐Ÿ‘พ *Link Cables* and ๐Ÿ“ป *Wireless Adapters*, using the **same API**. +- [๐Ÿ‘พ](#-LinkCable) [LinkCable.hpp](lib/LinkCable.hpp): The classic 16-bit **Multi-Play mode** (up to 4 players) using a GBA Link Cable! +- [๐Ÿ’ป](#-LinkCableMultiboot) [LinkCableMultiboot.hpp](lib/LinkCableMultiboot.hpp): โ€Send **Multiboot software** (small 256KiB ROMs) to other GBAs with no cartridge! +- [๐Ÿ”Œ](#-LinkGPIO) [LinkGPIO.hpp](lib/LinkGPIO.hpp): Use the Link Port however you want to control **any device** (like LEDs, rumble motors, and that kind of stuff)! +- [๐Ÿ”—](#-LinkSPI) [LinkSPI.hpp](lib/LinkSPI.hpp): Connect with a PC (like a **Raspberry Pi**) or another GBA (with a GBC Link Cable) using this mode. Transfer up to 2Mbit/s! +- [๐Ÿ“ป](#-LinkWireless) [LinkWireless.hpp](lib/LinkWireless.hpp): Connect up to 5 consoles with the **Wireless Adapter**! +- [๐ŸŒŽ](#-LinkUniversal) [LinkUniversal.hpp](lib/LinkUniversal.hpp): Add multiplayer support to your game, both with ๐Ÿ‘พ *Link Cables* and ๐Ÿ“ป *Wireless Adapters*, using the **same API**. *(click on the emojis for documentation)* @@ -15,10 +15,11 @@ A set of Game Boy Advance (GBA) C++ libraries to interact with the Serial Port. ## Usage -- Include the library you want (e.g. [LinkCable.h](lib/LinkCable.h)) in your game code, and refer to its comments for instructions. +- Include the library you want (e.g. [LinkCable.hpp](lib/LinkCable.hpp)) in your game code, and refer to its comments for instructions. - Check out the [examples](examples) folder. * Builds are available in *Releases*. - * They can be tested on real GBAs or using emulators (*NO$GBA*, *mGBA*, or *VBA-M*). + * They can be tested on real GBAs or using emulators (*mGBA*, *NO$GBA*, or *VBA-M*). + * For `LinkCable`/`LinkWireless`/`LinkUniversal` there are stress tests that you can use to tweak your configuration. ### Makefile actions (for all examples) @@ -45,9 +46,14 @@ Name | Type | Default | Description `baudRate` | **BaudRate** | `BAUD_RATE_1` | Sets a specific baud rate. `timeout` | **u32** | `3` | Number of *frames* without an `II_SERIAL` IRQ to reset the connection. `remoteTimeout` | **u32** | `5` | Number of *messages* with `0xFFFF` to mark a player as disconnected. -`interval` | **u16** | `50` | Number of *1024cycles* (61.04ฮผs) ticks between messages *(50 = 3.052ms)*. It's the interval of Timer #`sendTimerId`. +`interval` | **u16** | `50` | Number of *1024-cycle ticks* (61.04ฮผs) between transfers *(50 = 3.052ms)*. It's the interval of Timer #`sendTimerId`. Lower values will transfer faster but also consume more CPU. `sendTimerId` | **u8** *(0~3)* | `3` | GBA Timer to use for sending. +You can update these values at any time without creating a new instance: +- Call `deactivate()`. +- Mutate the `config` property. +- Call `activate()`. + You can also change these compile-time constants: - `LINK_CABLE_QUEUE_SIZE`: to set a custom buffer size (how many incoming and outgoing messages the queues can store at max **per player**). The default value is `15`, which seems fine for most games. @@ -64,9 +70,9 @@ Name | Return type | Description `sync()` | - | Call this method every time you need to fetch new data. `waitFor(playerId)` | **bool** | Waits for data from player #`playerId`. Returns `true` on success, or `false` on disconnection. `waitFor(playerId, cancel)` | **bool** | Like `waitFor(playerId)` but accepts a `cancel()` function. The library will continuously invoke it, and abort the wait if it returns `true`. -`canRead(playerId)` | **bool** | Returns `true` if there are pending messages from player #`playerId`. +`canRead(playerId)` | **bool** | Returns `true` if there are pending messages from player #`playerId`. Keep in mind that if this returns `false`, it will keep doing so until you *fetch new data* with `sync()`. `read(playerId)` | **u16** | Dequeues and returns the next message from player #`playerId`. -`peek(playerId)` | **u16** | Returns the next message from player #`playerId` without dequeuing it. +`peek(playerId)` | **u16** | Returns the next message from player #`playerId` without dequeuing it. `send(data)` | - | Sends `data` to all connected players. โš ๏ธ `0xFFFF` and `0x0` are reserved values, so don't send them! @@ -150,7 +156,7 @@ This is a driver for an accessory that enables wireless games up to 5 players. T The library, by default, implements a lightweight protocol (on top of the adapter's message system) that sends packet IDs and checksums. This allows detecting disconnections, forwarding messages to all nodes, and retransmitting to prevent packet loss. -![photo](https://user-images.githubusercontent.com/1631752/216233248-1f8ee26e-c8c1-418a-ad02-ad7c283dc49f.png) +https://github.com/afska/gba-link-connection/assets/1631752/7eeafc49-2dfa-4902-aa78-57b391720564 ## Constructor @@ -163,10 +169,15 @@ Name | Type | Default | Description `maxPlayers` | **u8** *(2~5)* | `5` | Maximum number of allowed players. The adapter will accept connections after reaching the limit, but the library will ignore them. If your game only supports -for example- two players, set this to `2` as it will make transfers faster. `timeout` | **u32** | `8` | Number of *frames* without receiving *any* data to reset the connection. `remoteTimeout` | **u32** | `10` | Number of *successful transfers* without a message from a client to mark the player as disconnected. -`interval` | **u16** | `50` | Number of *1024cycles* (61.04ฮผs) ticks between transfers *(50 = 3.052ms)*. It's the interval of Timer #`sendTimerId`. +`interval` | **u16** | `50` | Number of *1024-cycle ticks* (61.04ฮผs) between transfers *(50 = 3.052ms)*. It's the interval of Timer #`sendTimerId`. Lower values will transfer faster but also consume more CPU. `sendTimerId` | **u8** *(0~3)* | `3` | GBA Timer to use for sending. `asyncACKTimerId` | **s8** *(0~3 or -1)* | `-1` | GBA Timer to use for ACKs. If you have free timers, use one here to reduce CPU usage. +You can update these values at any time without creating a new instance: +- Call `deactivate()`. +- Mutate the `config` property. +- Call `activate()`. + You can also change these compile-time constants: - `LINK_WIRELESS_QUEUE_SIZE`: to set a custom buffer size (how many incoming and outgoing messages the queues can store at max). The default value is `30`, which seems fine for most games. - `LINK_WIRELESS_MAX_COMMAND_RESPONSE_LENGTH`: to set the biggest allowed response from the adapter. The default value is `50`, which allows reading all user messages (max receive length is `21`) and -in theory- up to `7` broadcasting servers *(7 values per broadcast * 7 = 49 responses)*. This library was only tested with `4` adapters, so the real maximum is unknown. @@ -205,7 +216,7 @@ Name | Return type | Description A multiuse library that doesn't care whether you plug a Link Cable or a Wireless Adapter. It continuously switches between both and tries to connect to other peers, supporting the hot swapping of cables and adapters and all the features from [๐Ÿ‘พ LinkCable](#-LinkCable) and [๐Ÿ“ป LinkWireless](#-LinkWireless). -https://github.com/afska/gba-link-connection/assets/1631752/b2900110-3b27-4cdb-8ae1-744878d6384b +https://github.com/afska/gba-link-connection/assets/1631752/d1f49a48-6b17-4954-99d6-d0b7586f5730 ## Constructor diff --git a/examples/LinkCableMultiboot_demo/src/main.cpp b/examples/LinkCableMultiboot_demo/src/main.cpp index 23720af..ee3f37b 100644 --- a/examples/LinkCableMultiboot_demo/src/main.cpp +++ b/examples/LinkCableMultiboot_demo/src/main.cpp @@ -2,9 +2,9 @@ #include #include "../../_lib/interrupt.h" -#include "../../../lib/LinkCable.h" +#include "../../../lib/LinkCable.hpp" // (0) Include the header -#include "../../../lib/LinkCableMultiboot.h" +#include "../../../lib/LinkCableMultiboot.hpp" void log(std::string text); diff --git a/examples/LinkCable_basic/src/main.cpp b/examples/LinkCable_basic/src/main.cpp index 2cd75d5..187d368 100644 --- a/examples/LinkCable_basic/src/main.cpp +++ b/examples/LinkCable_basic/src/main.cpp @@ -6,7 +6,7 @@ // This example sends the pressed buttons to other players. // (0) Include the header -#include "../../../lib/LinkCable.h" +#include "../../../lib/LinkCable.hpp" void log(std::string text); diff --git a/examples/LinkCable_full/src/main.h b/examples/LinkCable_full/src/main.h index 860815c..0f685d0 100644 --- a/examples/LinkCable_full/src/main.h +++ b/examples/LinkCable_full/src/main.h @@ -2,8 +2,8 @@ #define MAIN_H #include -#include "../../../lib/LinkCable.h" -#include "../../../lib/LinkUniversal.h" +#include "../../../lib/LinkCable.hpp" +#include "../../../lib/LinkUniversal.hpp" // #define USE_LINK_UNIVERSAL diff --git a/examples/LinkCable_stress/src/main.h b/examples/LinkCable_stress/src/main.h index 83fb5d0..030bdb3 100644 --- a/examples/LinkCable_stress/src/main.h +++ b/examples/LinkCable_stress/src/main.h @@ -1,6 +1,6 @@ #include -#include "../../../lib/LinkCable.h" -#include "../../../lib/LinkUniversal.h" +#include "../../../lib/LinkCable.hpp" +#include "../../../lib/LinkUniversal.hpp" // #define USE_LINK_UNIVERSAL diff --git a/examples/LinkGPIO_demo/src/main.cpp b/examples/LinkGPIO_demo/src/main.cpp index cd66cb0..b6cfb34 100644 --- a/examples/LinkGPIO_demo/src/main.cpp +++ b/examples/LinkGPIO_demo/src/main.cpp @@ -2,7 +2,7 @@ #include // (0) Include the header -#include "../../../lib/LinkGPIO.h" +#include "../../../lib/LinkGPIO.hpp" void log(std::string text); std::string mode(std::string name, LinkGPIO::Pin pin); diff --git a/examples/LinkSPI_demo/src/main.cpp b/examples/LinkSPI_demo/src/main.cpp index 9d7296f..00f8873 100644 --- a/examples/LinkSPI_demo/src/main.cpp +++ b/examples/LinkSPI_demo/src/main.cpp @@ -3,7 +3,7 @@ #include "../../_lib/interrupt.h" // (0) Include the header -#include "../../../lib/LinkSPI.h" +#include "../../../lib/LinkSPI.hpp" void log(std::string text); void wait(u32 verticalLines); diff --git a/examples/LinkUniversal_basic/src/main.cpp b/examples/LinkUniversal_basic/src/main.cpp index 52058bf..474b3f6 100644 --- a/examples/LinkUniversal_basic/src/main.cpp +++ b/examples/LinkUniversal_basic/src/main.cpp @@ -6,7 +6,7 @@ // This example sends the pressed buttons to other players. // (0) Include the header -#include "../../../lib/LinkUniversal.h" +#include "../../../lib/LinkUniversal.hpp" void log(std::string text); void waitFor(u16 key); diff --git a/examples/LinkWireless_demo/src/main.cpp b/examples/LinkWireless_demo/src/main.cpp index a56716a..6543ff9 100644 --- a/examples/LinkWireless_demo/src/main.cpp +++ b/examples/LinkWireless_demo/src/main.cpp @@ -5,7 +5,7 @@ #include "../../_lib/interrupt.h" // (0) Include the header -#include "../../../lib/LinkWireless.h" +#include "../../../lib/LinkWireless.hpp" #ifdef PROFILING_ENABLED #include diff --git a/examples/compile.sh b/examples/compile.sh index 392ea0b..50f24fd 100644 --- a/examples/compile.sh +++ b/examples/compile.sh @@ -59,10 +59,10 @@ cp LinkWireless_demo.gba ../ cd .. cd LinkWireless_demo/ -sed -i -e "s/\/\/ #define PROFILING_ENABLED/#define PROFILING_ENABLED/g" ../../lib/LinkWireless.h +sed -i -e "s/\/\/ #define PROFILING_ENABLED/#define PROFILING_ENABLED/g" ../../lib/LinkWireless.hpp mv LinkWireless_demo.gba backup.gba make rebuild cp LinkWireless_demo.gba ../LinkWireless_demo_profiler.gba mv backup.gba LinkWireless_demo.gba -sed -i -e "s/#define PROFILING_ENABLED/\/\/ #define PROFILING_ENABLED/g" ../../lib/LinkWireless.h +sed -i -e "s/#define PROFILING_ENABLED/\/\/ #define PROFILING_ENABLED/g" ../../lib/LinkWireless.hpp cd .. diff --git a/lib/LinkCable.h b/lib/LinkCable.hpp similarity index 100% rename from lib/LinkCable.h rename to lib/LinkCable.hpp diff --git a/lib/LinkCableMultiboot.h b/lib/LinkCableMultiboot.hpp similarity index 100% rename from lib/LinkCableMultiboot.h rename to lib/LinkCableMultiboot.hpp diff --git a/lib/LinkGPIO.h b/lib/LinkGPIO.hpp similarity index 100% rename from lib/LinkGPIO.h rename to lib/LinkGPIO.hpp diff --git a/lib/LinkSPI.h b/lib/LinkSPI.hpp similarity index 100% rename from lib/LinkSPI.h rename to lib/LinkSPI.hpp diff --git a/lib/LinkUniversal.h b/lib/LinkUniversal.hpp similarity index 99% rename from lib/LinkUniversal.h rename to lib/LinkUniversal.hpp index 7ee1d06..f101688 100644 --- a/lib/LinkUniversal.h +++ b/lib/LinkUniversal.hpp @@ -40,8 +40,8 @@ #include #include -#include "LinkCable.h" -#include "LinkWireless.h" +#include "LinkCable.hpp" +#include "LinkWireless.hpp" #define LINK_UNIVERSAL_MAX_PLAYERS LINK_CABLE_MAX_PLAYERS #define LINK_UNIVERSAL_DISCONNECTED LINK_CABLE_DISCONNECTED diff --git a/lib/LinkWireless.h b/lib/LinkWireless.hpp similarity index 99% rename from lib/LinkWireless.h rename to lib/LinkWireless.hpp index 3c7efbc..75a18b5 100644 --- a/lib/LinkWireless.h +++ b/lib/LinkWireless.hpp @@ -56,8 +56,8 @@ #include #include -#include "LinkGPIO.h" -#include "LinkSPI.h" +#include "LinkGPIO.hpp" +#include "LinkSPI.hpp" // #include @@ -840,7 +840,6 @@ class LinkWireless { } case LINK_WIRELESS_COMMAND_END_HOST: { // EndHost (end) - break; } case LINK_WIRELESS_COMMAND_SEND_DATA: { @@ -854,7 +853,6 @@ class LinkWireless { } case LINK_WIRELESS_COMMAND_RECEIVE_DATA: { // ReceiveData (end) - if (asyncCommand.result.responsesSize == 0) break;