diff --git a/README.md b/README.md index 8f27b25..5012d3f 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ It temporarily applies patches to the IOS-PAD module responsible for Bluetooth c - Connect up to 7 controllers wirelessly via Bluetooth - Rumble support - Battery levels +- Button and stick remapping (only for Bloopair controllers) ## Supported controllers - Nintendo Switch Pro Controller @@ -22,19 +23,31 @@ To pair a DualShock 3 to the console, see the [Pairing a DualShock 3](#pairing-a ## Installation - Download and extract the latest .zip from the [releases page](https://github.com/GaryOderNichts/Bloopair/releases). - Copy the `30_bloopair.rpx` from the .zip file to the `modules/setup/` folder of your target environment on the SD Card. - This would be `wiiu/environments/tiramisu/modules/setup/` for Tiramisu. + This would be `wiiu/environments/aroma/modules/setup/` for Aroma. - Copy the `wiiu` folder from the .zip and copy it to the root of your SD Card. If you're using aroma you can delete the `Koopair.rpx` in the `wiiu/apps` folder and use the .wuhb instead. -Make sure you're using Tiramisu or Aroma. Follow https://wiiu.hacks.guide/#/ to setup Tiramisu. -More info about Tiramisu here: https://maschell.github.io/homebrew/2021/12/31/tiramisu.html +Make sure you're using Aroma or Tiramisu. Follow https://wiiu.hacks.guide/#/ to setup Aroma. ## Usage -- Once you're booted into Tiramisu and are in the Wii U menu, press the SYNC button on your console and controller. +- Once you're booted into Aroma or Tiramisu and are in the Wii U menu, press the SYNC button on your console and controller. - Wait until the Controller is connected. If a controller had been paired in the past, simply turn it on again and it should reconnect. +## Koopair +Koopair is the Bloopair companion app which comes with Bloopair. + + + + +Koopair supports: +- Testing connected controllers +- Creating mappings for buttons and sticks +- Editing controller options +- Managing configuration files +- Pairing DualShock 3 controllers + ## Pairing a DualShock 3 The DualShock 3 needs to be paired using a USB cable. After the initial pairing it can be used like any other wireless Bluetooth controller. - Open Koopair from the Wii U menu or Homebrew Launcher. Now open the "Controller Pairing" option on the menu. @@ -47,16 +60,20 @@ The DualShock 3 is now ready to use with the console. ## FAQ / Troubleshooting -### My controller doesn't pair to the console +**My controller doesn't pair to the console** Make sure Bloopair is running and both the console and the controller are in SYNC mode. Also make sure the controller is on the supported list. Wait for about a minute, and if nothing happens restart your console and redo the process. You can also try [clearing controller syncs](https://en-americas-support.nintendo.com/app/answers/detail/a_id/1705/~/how-to-clear-all-syncs). -### Will you add support for controller xyz? +**Will you add support for controller xyz?** Possibly, I've for now added support for all the controllers I currently own. Maybe I can get a few more controllers which I could add support for. Pull requests for different controllers are always welcome. +**Where are configuration files stored?** +Bloopair loads configuration files from the `wiiu/bloopair` folder on your SD Card. +This means configurations work across multiple environments. + ## To-Do - Support more controllers - Bluetooth LE support (Unlikely, only partially supported by the Bluetooth Stack) @@ -87,5 +104,6 @@ Koopair additionally requires the following packages: - wiiu-sdl2 - wiiu-sdl2_gfx - wiiu-sdl2_ttf +- wiiu-sdl2_image Run `make`. diff --git a/dist/wiiu/apps/Koopair/icon.png b/dist/wiiu/apps/Koopair/icon.png index a7a6c05..aec5151 100644 Binary files a/dist/wiiu/apps/Koopair/icon.png and b/dist/wiiu/apps/Koopair/icon.png differ diff --git a/koopair/Makefile b/koopair/Makefile index e16e5bb..ce7d7ea 100644 --- a/koopair/Makefile +++ b/koopair/Makefile @@ -13,7 +13,7 @@ TOPDIR ?= $(CURDIR) # APP_SHORTNAME sets the short name of the application # APP_AUTHOR sets the author of the application #------------------------------------------------------------------------------- -APP_NAME := Bloopair Companion App +APP_NAME := Koopair APP_SHORTNAME := Koopair APP_AUTHOR := GaryOderNichts APP_VERSION := 1.0.0 @@ -56,7 +56,7 @@ CXXFLAGS := $(CFLAGS) -std=gnu++20 ASFLAGS := $(ARCH) LDFLAGS = $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) -LIBS := -lSDL2 -lSDL2_ttf -lSDL2_gfx -lfreetype -lharfbuzz -lfreetype -lpng -lbz2 -lz -lbloopair -lwut +LIBS := -lSDL2 -lSDL2_ttf -lSDL2_gfx -lSDL2_image -lfreetype -lharfbuzz -lfreetype -lpng -lbz2 -lz -lbloopair -lwut ifeq ($(DEBUG), 1) CFLAGS += -g -DCOMMIT_HASH=\"$(BLOOPAIR_COMMIT_HASH)\" @@ -200,6 +200,12 @@ $(OFILES_SRC) : $(HFILES_BIN) @echo $(notdir $<) @$(bin2o) +#------------------------------------------------------------------------------- +%.png.o %_png.h : %.png +#------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + -include $(DEPENDS) #------------------------------------------------------------------------------- diff --git a/koopair/README.md b/koopair/README.md index cbd1c61..b72b7dd 100644 --- a/koopair/README.md +++ b/koopair/README.md @@ -6,3 +6,4 @@ Koopair additionally requires the following packages: - wiiu-sdl2 - wiiu-sdl2_gfx - wiiu-sdl2_ttf +- wiiu-sdl2_image diff --git a/koopair/data/shell.png b/koopair/data/shell.png new file mode 100644 index 0000000..077f04c Binary files /dev/null and b/koopair/data/shell.png differ diff --git a/koopair/icon.png b/koopair/icon.png index 4c68711..11843e5 100644 Binary files a/koopair/icon.png and b/koopair/icon.png differ diff --git a/koopair/source/Controller.cpp b/koopair/source/Controller.cpp index 076903d..2869f7c 100644 --- a/koopair/source/Controller.cpp +++ b/koopair/source/Controller.cpp @@ -248,6 +248,11 @@ bool KPADController::Update() MAP_BTN(WPAD_CLASSIC_BUTTON_R, BUTTON_R); MAP_BTN(WPAD_CLASSIC_BUTTON_L, BUTTON_L); #undef MAP_BTN + + mStickL.x = mStatus.classic.leftStick.x; + mStickL.y = mStatus.classic.leftStick.y; + mStickR.x = mStatus.classic.rightStick.x; + mStickR.y = mStatus.classic.rightStick.y; } return true; @@ -324,7 +329,8 @@ std::array KPADController::GetBDA() const } CombinedInputController::CombinedInputController() : Controller(), - mName("Combined Controller") + mName("Combined Controller"), + mPreviousButtons() { } @@ -342,9 +348,35 @@ bool CombinedInputController::Combine(const std::vector& cont mButtonsHeld |= c->GetButtonsHeld(); mButtonsTriggered |= c->GetButtonsTriggered(); + if (c->GetStickL().x > 0.2f) { + if ((mPreviousButtons & BUTTON_RIGHT) == 0) { + mButtonsTriggered |= BUTTON_RIGHT; + } + mButtonsHeld |= BUTTON_RIGHT; + } else if (c->GetStickL().x < -0.2f) { + if ((mPreviousButtons & BUTTON_LEFT) == 0) { + mButtonsTriggered |= BUTTON_LEFT; + } + mButtonsHeld |= BUTTON_LEFT; + } + if (c->GetStickL().y > 0.2f) { + if ((mPreviousButtons & BUTTON_UP) == 0) { + mButtonsTriggered |= BUTTON_UP; + } + mButtonsHeld |= BUTTON_UP; + } else if (c->GetStickL().y < -0.2f) { + if ((mPreviousButtons & BUTTON_DOWN) == 0) { + mButtonsTriggered |= BUTTON_DOWN; + } + mButtonsHeld |= BUTTON_DOWN; + } + + // TODO sticks } + mPreviousButtons = mButtonsHeld; + return true; } diff --git a/koopair/source/Controller.hpp b/koopair/source/Controller.hpp index 06aabf8..416807f 100644 --- a/koopair/source/Controller.hpp +++ b/koopair/source/Controller.hpp @@ -186,4 +186,6 @@ class CombinedInputController : public Controller { private: std::string mName; + + Buttons mPreviousButtons; }; diff --git a/koopair/source/Gfx.cpp b/koopair/source/Gfx.cpp index 7c85d1d..d12a489 100644 --- a/koopair/source/Gfx.cpp +++ b/koopair/source/Gfx.cpp @@ -17,6 +17,7 @@ #include "Gfx.hpp" #include "SDL_FontCache.h" #include +#include #include #include @@ -25,6 +26,7 @@ #include #include +#include namespace { @@ -45,6 +47,8 @@ TTF_Font* iconFont = nullptr; std::map iconCache; +SDL_Texture* appIcon = nullptr; + FC_Font* GetFontForSize(int size) { if (fontMap.contains(size)) { @@ -67,6 +71,10 @@ FC_Font* GetFontForSize(int size) SDL_Texture* LoadIcon(Uint16 icon) { + if (icon == Gfx::APP_ICON) { + return appIcon; + } + if (iconCache.contains(icon)) { return iconCache[icon]; } @@ -123,17 +131,22 @@ bool Init() return false; } - if (!FC_LoadFont_RW(monospaceFont, renderer, SDL_RWFromMem((void*)ter_u32b_bdf, ter_u32b_bdf_size), 1, 32, Gfx::COLOR_BLACK, TTF_STYLE_NORMAL)) { + if (!FC_LoadFont_RW(monospaceFont, renderer, SDL_RWFromConstMem(ter_u32b_bdf, ter_u32b_bdf_size), 1, 32, Gfx::COLOR_BLACK, TTF_STYLE_NORMAL)) { FC_FreeFont(monospaceFont); return false; } // icons @256 should be large enough for our needs - iconFont = TTF_OpenFontRW(SDL_RWFromMem((void*)fa_solid_900_ttf, fa_solid_900_ttf_size), 1, 256); + iconFont = TTF_OpenFontRW(SDL_RWFromConstMem(fa_solid_900_ttf, fa_solid_900_ttf_size), 1, 256); if (!iconFont) { return false; } + appIcon = IMG_LoadTextureTyped_RW(renderer, SDL_RWFromConstMem(shell_png, shell_png_size), 1, "PNG"); + if (!appIcon) { + return false; + } + return true; } @@ -147,6 +160,7 @@ void Shutdown() SDL_DestroyTexture(value); } + SDL_DestroyTexture(appIcon); FC_FreeFont(monospaceFont); TTF_CloseFont(iconFont); TTF_Quit(); diff --git a/koopair/source/Gfx.hpp b/koopair/source/Gfx.hpp index e15123e..dc22e44 100644 --- a/koopair/source/Gfx.hpp +++ b/koopair/source/Gfx.hpp @@ -39,6 +39,8 @@ constexpr SDL_Color COLOR_BARS = { 0x00, 0x22, 0x42, 0xff }; constexpr SDL_Color COLOR_ERROR = { 0xff, 0x33, 0x33, 0xff }; constexpr SDL_Color COLOR_WIIU = { 0x00, 0x95, 0xc7, 0xff }; +constexpr uint16_t APP_ICON = 0xfffe; + enum AlignFlags { ALIGN_LEFT = 1 << 0, ALIGN_RIGHT = 1 << 1, diff --git a/koopair/source/Screen.cpp b/koopair/source/Screen.cpp index caf3c7f..649631b 100644 --- a/koopair/source/Screen.cpp +++ b/koopair/source/Screen.cpp @@ -23,12 +23,12 @@ void Screen::DrawTopBar(const char* name) Gfx::DrawRectFilled(0, 0, Gfx::SCREEN_WIDTH, 75, Gfx::COLOR_BARS); // draw top bar content - Gfx::DrawIcon(32, 75 / 2, 60, Gfx::COLOR_TEXT, 0xffff, Gfx::ALIGN_VERTICAL); - Gfx::Print(128, 75 / 2, 60, Gfx::COLOR_TEXT, "Koopair", Gfx::ALIGN_VERTICAL); + Gfx::DrawIcon(68, 75 / 2, 60, Gfx::COLOR_TEXT, Gfx::APP_ICON, Gfx::ALIGN_CENTER); + Gfx::Print(128 + 8, 75 / 2, 60, Gfx::COLOR_TEXT, "Koopair", Gfx::ALIGN_VERTICAL); #ifdef NDEBUG - Gfx::Print(Gfx::GetTextWidth(60, "Koopair") + 128 + 16, 75 / 2 + 5, 50, Gfx::COLOR_ALT_TEXT, "v" APP_VERSION, Gfx::ALIGN_VERTICAL); + Gfx::Print(Gfx::GetTextWidth(60, "Koopair") + 128 + 8 + 16, 75 / 2 + 5, 50, Gfx::COLOR_ALT_TEXT, "v" APP_VERSION, Gfx::ALIGN_VERTICAL); #else - Gfx::Print(Gfx::GetTextWidth(60, "Koopair") + 128 + 16, 75 / 2 + 5, 50, Gfx::COLOR_ALT_TEXT, "v" APP_VERSION "-" + std::string(COMMIT_HASH).substr(0, 7), Gfx::ALIGN_VERTICAL); + Gfx::Print(Gfx::GetTextWidth(60, "Koopair") + 128 + 8 + 16, 75 / 2 + 5, 50, Gfx::COLOR_ALT_TEXT, "v" APP_VERSION "-" + std::string(COMMIT_HASH).substr(0, 7), Gfx::ALIGN_VERTICAL); #endif if (name) Gfx::Print(Gfx::SCREEN_WIDTH - 32, 75 / 2, 50, Gfx::COLOR_ALT_TEXT, name, Gfx::ALIGN_VERTICAL | Gfx::ALIGN_RIGHT); diff --git a/koopair/source/screens/ControllerConfigurationsScreen.cpp b/koopair/source/screens/ControllerConfigurationsScreen.cpp index c7f30bb..8baaeca 100644 --- a/koopair/source/screens/ControllerConfigurationsScreen.cpp +++ b/koopair/source/screens/ControllerConfigurationsScreen.cpp @@ -42,8 +42,7 @@ ControllerConfigurationsScreen::~ControllerConfigurationsScreen() void ControllerConfigurationsScreen::Draw() { - // TODO - DrawTopBar("ControllerConfigurationsScreen"); + DrawTopBar("Controller Configurations"); if (!mConfigurations.empty()) { int drawIndex = 0; diff --git a/koopair/source/screens/ControllerMappingScreen.cpp b/koopair/source/screens/ControllerMappingScreen.cpp index 012a462..faf13eb 100644 --- a/koopair/source/screens/ControllerMappingScreen.cpp +++ b/koopair/source/screens/ControllerMappingScreen.cpp @@ -245,8 +245,7 @@ ControllerMappingScreen::~ControllerMappingScreen() void ControllerMappingScreen::Draw() { - // TODO - DrawTopBar("ControllerMappingScreen"); + DrawTopBar("Controller Mapping"); int drawIndex = 0; for (size_t i = mSelectionStart; i < mSelectionEnd; i++) { diff --git a/koopair/source/screens/ControllerOptionsScreen.cpp b/koopair/source/screens/ControllerOptionsScreen.cpp index b8a71ac..906bb46 100644 --- a/koopair/source/screens/ControllerOptionsScreen.cpp +++ b/koopair/source/screens/ControllerOptionsScreen.cpp @@ -82,7 +82,7 @@ ControllerOptionsScreen::~ControllerOptionsScreen() void ControllerOptionsScreen::Draw() { - DrawTopBar("ControllerOptionsScreen"); + DrawTopBar("Controller Options"); uint32_t yOff = 128; diff --git a/koopair/source/screens/ControllerPairingScreen.cpp b/koopair/source/screens/ControllerPairingScreen.cpp index d5973f8..7637b1b 100644 --- a/koopair/source/screens/ControllerPairingScreen.cpp +++ b/koopair/source/screens/ControllerPairingScreen.cpp @@ -73,8 +73,7 @@ ControllerPairingScreen::~ControllerPairingScreen() void ControllerPairingScreen::Draw() { - // TODO - DrawTopBar("ControllerPairingScreen"); + DrawTopBar("Controller Pairing"); Gfx::Print(Gfx::SCREEN_WIDTH / 2, Gfx::SCREEN_HEIGHT / 2, 60, Gfx::COLOR_TEXT, "Connect a DualShock 3 using a USB cable\nto any USB port of the system to pair it.\n" diff --git a/koopair/source/screens/MainScreen.cpp b/koopair/source/screens/MainScreen.cpp index 5663095..86730ae 100644 --- a/koopair/source/screens/MainScreen.cpp +++ b/koopair/source/screens/MainScreen.cpp @@ -26,9 +26,9 @@ namespace { -// Let's make sure to not break API for minor and patch versions +// Let's make sure to not break API for patch versions constexpr uint32_t kMinBloopairVersion = BLOOPAIR_VERSION(1, 0, 0); -constexpr uint32_t kMaxBloopairVersion = BLOOPAIR_VERSION(1, 255, 255); +constexpr uint32_t kMaxBloopairVersion = BLOOPAIR_VERSION(1, 0, 255); } diff --git a/koopair/source/screens/SettingsScreen.cpp b/koopair/source/screens/SettingsScreen.cpp index 2d0b3a2..96d4515 100644 --- a/koopair/source/screens/SettingsScreen.cpp +++ b/koopair/source/screens/SettingsScreen.cpp @@ -27,8 +27,7 @@ SettingsScreen::~SettingsScreen() void SettingsScreen::Draw() { - // TODO - DrawTopBar("SettingsScreen"); + DrawTopBar("Settings"); Gfx::Print(Gfx::SCREEN_WIDTH / 2, Gfx::SCREEN_HEIGHT / 2, 60, Gfx::COLOR_TEXT, "Nothing here yet :)", Gfx::ALIGN_CENTER);