Skip to content

Commit 607a01c

Browse files
author
Daniel K. O. (dkosmari)
committed
Merged with main.
2 parents e3b5e87 + 416d060 commit 607a01c

18 files changed

Lines changed: 308 additions & 224 deletions

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ jobs:
99
clang-format:
1010
runs-on: ubuntu-22.04
1111
steps:
12-
- uses: actions/checkout@v4
12+
- uses: actions/checkout@v6
1313
- name: clang-format
1414
run: |
1515
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source
1616
build-binary:
1717
runs-on: ubuntu-22.04
1818
needs: clang-format
1919
steps:
20-
- uses: actions/checkout@v4
20+
- uses: actions/checkout@v6
2121
- name: create version.h
2222
run: |
2323
git_hash=$(git rev-parse --short "$GITHUB_SHA")

.github/workflows/pr.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ jobs:
66
clang-format:
77
runs-on: ubuntu-22.04
88
steps:
9-
- uses: actions/checkout@v4
9+
- uses: actions/checkout@v6
1010
- name: clang-format
1111
run: |
1212
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source
1313
check-build-with-logging:
1414
runs-on: ubuntu-22.04
1515
needs: clang-format
1616
steps:
17-
- uses: actions/checkout@v4
17+
- uses: actions/checkout@v6
1818
- name: build binary with logging
1919
run: |
2020
docker build . -t builder
@@ -25,7 +25,7 @@ jobs:
2525
runs-on: ubuntu-22.04
2626
needs: clang-format
2727
steps:
28-
- uses: actions/checkout@v4
28+
- uses: actions/checkout@v6
2929
- name: create version.h
3030
run: |
3131
git_hash=$(git rev-parse --short "${{ github.event.pull_request.head.sha }}")

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ cmake-build-debug/
99
CMakeLists.txt
1010
*.wms
1111
*.zip
12+
docs/

.gitmodules

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[submodule "external/libbuttoncombo"]
2+
path = external/libbuttoncombo
3+
url = https://github.com/wiiu-env/libbuttoncombo.git
4+
[submodule "external/libfunctionpatcher"]
5+
path = external/libfunctionpatcher
6+
url = https://github.com/wiiu-env/libfunctionpatcher.git
7+
[submodule "external/WiiUModuleSystem"]
8+
path = external/WiiUModuleSystem
9+
url = https://github.com/wiiu-env/WiiUModuleSystem.git

Dockerfile

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
FROM ghcr.io/wiiu-env/devkitppc:20241128
1+
FROM ghcr.io/wiiu-env/devkitppc:20260225
22

3-
COPY --from=ghcr.io/wiiu-env/libbuttoncombo:20250125-cb22627 /artifacts $DEVKITPRO
4-
COPY --from=ghcr.io/wiiu-env/libfunctionpatcher:20241012 /artifacts $DEVKITPRO
5-
COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:20240424 /artifacts $DEVKITPRO
3+
COPY --from=ghcr.io/wiiu-env/libbuttoncombo:20260331 /artifacts $DEVKITPRO
4+
COPY --from=ghcr.io/wiiu-env/libfunctionpatcher:20260331 /artifacts $DEVKITPRO
5+
COPY --from=ghcr.io/wiiu-env/wiiumodulesystem:20260418 /artifacts $DEVKITPRO
66

7-
WORKDIR project
7+
WORKDIR /project

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ INCLUDES := source
2828
#-------------------------------------------------------------------------------
2929
# options for code generation
3030
#-------------------------------------------------------------------------------
31-
CFLAGS := -Wall -Wextra -O2 -ffunction-sections\
31+
CFLAGS := -Wall -Wextra -Werror -Os -ffunction-sections\
3232
$(MACHDEP)
3333

3434
CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__

README.md

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,61 @@
1+
# ButtonComboModule
2+
13
[![CI-Release](https://github.com/wiiu-env/ButtonComboModule/actions/workflows/ci.yml/badge.svg)](https://github.com/wiiu-env/ButtonComboModule/actions/workflows/ci.yml)
24

5+
**ButtonComboModule** is a Wii U Module System (WUMS) module that provides system-wide button combination detection. It
6+
allows other homebrew applications and modules to easily register callbacks for specific button presses or holds across
7+
various controllers (GamePad, Pro Controller, Wii Remote, etc.).
8+
39
## Usage
4-
(`[ENVIRONMENT]` is a placeholder for the actual environment name.)
510

6-
1. Copy the file `ButtonComboModule.wms` into `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
7-
2. Requires the [WUMSLoader](https://github.com/wiiu-env/WUMSLoader) in `sd:/wiiu/environments/[ENVIRONMENT]/modules/setup`.
8-
3. Requires the [FunctionPatcherModule](https://github.com/wiiu-env/FunctionPatcherModule) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
11+
(`[ENVIRONMENT]` is a placeholder for the actual environment name, e.g., `tiramisu` or `aroma`.)
12+
13+
1. Copy the file `ButtonComboModule.wms` into `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
14+
2. Requires the [WUMSLoader](https://github.com/wiiu-env/WUMSLoader) in
15+
`sd:/wiiu/environments/[ENVIRONMENT]/modules/setup`.
16+
3. Requires the [FunctionPatcherModule](https://github.com/wiiu-env/FunctionPatcherModule) in
17+
`sd:/wiiu/environments/[ENVIRONMENT]/modules`.
18+
19+
## Development
20+
21+
### Homebrew Applications (.rpx / .wuhb)
22+
23+
If you are developing a standard homebrew application and want to use system-wide button combos, you should use the
24+
**libbuttoncombo** client library.
25+
26+
* **Repository**: [wiiu-env/libbuttoncombo](https://github.com/wiiu-env/libbuttoncombo)
27+
28+
### WUPS Plugins (.wps)
29+
30+
If you are developing a plugin for the Wii U Plugin System (WUPS), you **should not** use `libbuttoncombo`.
931

10-
## Buildflags
32+
The [WiiUPluginSystem](https://github.com/wiiu-env/WiiUPluginSystem) (WUPS) library already provides built-in wrappers
33+
for the ButtonComboModule. You can use the WUPS API directly to register combos without linking an external library.
1134

12-
### Logging
13-
Building via `make` only logs errors (via OSReport). To enable logging via the [LoggingModule](https://github.com/wiiu-env/LoggingModule) set `DEBUG` to `1` or `VERBOSE`.
35+
## Building
1436

15-
`make` Logs errors only (via OSReport).
16-
`make DEBUG=1` Enables information and error logging via [LoggingModule](https://github.com/wiiu-env/LoggingModule).
17-
`make DEBUG=VERBOSE` Enables verbose information and error logging via [LoggingModule](https://github.com/wiiu-env/LoggingModule).
37+
To build this module, you need **devkitPro** installed with `wut` and `wums`. You also need the `libfunctionpatcher`
38+
libraries installed.
1839

19-
If the [LoggingModule](https://github.com/wiiu-env/LoggingModule) is not present, it'll fallback to UDP (Port 4405) and [CafeOS](https://github.com/wiiu-env/USBSerialLoggingModule) logging.
40+
### Build Flags (Logging)
2041

21-
## Building using the Dockerfile
42+
Building via `make` only logs critical errors via OSReport by default. To enable verbose logging via
43+
the [LoggingModule](https://github.com/wiiu-env/LoggingModule), set `DEBUG` to `1` or `VERBOSE`.
2244

23-
It's possible to use a docker image for building. This way you don't need anything installed on your host system.
45+
* `make`: Logs errors only (via OSReport).
46+
* `make DEBUG=1`: Enables information and error logging via [LoggingModule](https://github.com/wiiu-env/LoggingModule).
47+
* `make DEBUG=VERBOSE`: Enables verbose information and error logging
48+
via [LoggingModule](https://github.com/wiiu-env/LoggingModule).
49+
50+
If the [LoggingModule](https://github.com/wiiu-env/LoggingModule) is not present, it will fallback to UDP (Port 4405)
51+
and [USBSerialLoggingModule](https://github.com/wiiu-env/USBSerialLoggingModule) logging.
52+
53+
### Building using Docker
54+
55+
It is possible to use a Docker image for building. This way, you don't need anything installed on your host system.
2456

2557
```
26-
# Build docker image (only needed once)
58+
# Build Docker image (only needed once)
2759
docker build . -t buttoncombomodule-builder
2860
2961
# make
@@ -33,6 +65,14 @@ docker run -it --rm -v ${PWD}:/project buttoncombomodule-builder make
3365
docker run -it --rm -v ${PWD}:/project buttoncombomodule-builder make clean
3466
```
3567

36-
## Format the code via docker
68+
## Formatting
69+
70+
You can format the code via Docker:
71+
72+
```
73+
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source -i
74+
```
75+
76+
## License
3777

38-
`docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./source -i`
78+
This module is licensed under the **GPL-3.0**.

source/ButtonComboInfo.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ bool ButtonComboInfoIF::getMetaOptions(const ButtonComboModule_MetaOptionsOut &o
4242

4343
void ButtonComboInfoIF::setMetaOptions(const ButtonComboModule_MetaOptions options) {
4444
mLabel = options.label;
45-
DEBUG_FUNCTION_LINE("Updated label to: \"%s\", for %08X", mLabel.c_str(), getHandle().handle);
45+
DEBUG_FUNCTION_LINE("Updated label to: \"%s\", for %p", mLabel.c_str(), getHandle().handle);
4646
}
4747

4848
ButtonComboModule_CallbackOptions ButtonComboInfoIF::getCallbackOptions() const {
@@ -52,15 +52,15 @@ ButtonComboModule_CallbackOptions ButtonComboInfoIF::getCallbackOptions() const
5252
void ButtonComboInfoIF::setCallbackOptions(const ButtonComboModule_CallbackOptions options) {
5353
mCallback = options.callback;
5454
mContext = options.context;
55-
DEBUG_FUNCTION_LINE("Updated callback to: %08X(%08X), for %s %08X", mCallback, mContext, mLabel.c_str(), getHandle().handle);
55+
DEBUG_FUNCTION_LINE("Updated callback to: %p(%p), for %s handle: %p", mCallback, mContext, mLabel.c_str(), getHandle().handle);
5656
}
5757

5858
uint32_t ButtonComboInfoIF::getCombo() const {
5959
return mCombo;
6060
}
6161
void ButtonComboInfoIF::setCombo(const ButtonComboModule_Buttons combo) {
6262
mCombo = combo;
63-
DEBUG_FUNCTION_LINE("Updated combo to: %08X, for %s %08X", mCombo, mLabel.c_str(), getHandle().handle);
63+
DEBUG_FUNCTION_LINE("Updated combo to: %08X, for %s handle: %p", mCombo, mLabel.c_str(), getHandle().handle);
6464
resetPrevInput();
6565
}
6666

@@ -70,7 +70,7 @@ ButtonComboModule_ComboStatus ButtonComboInfoIF::getStatus() const {
7070

7171
void ButtonComboInfoIF::setStatus(const ButtonComboModule_ComboStatus status) {
7272
mStatus = status;
73-
DEBUG_FUNCTION_LINE("Updated status to: %08X, for %s %08X", mStatus, mLabel.c_str(), getHandle().handle);
73+
DEBUG_FUNCTION_LINE("Updated status to: %08X, for %s handle: %p", mStatus, mLabel.c_str(), getHandle().handle);
7474
}
7575

7676
ButtonComboModule_ControllerTypes ButtonComboInfoIF::getControllerMask() const {
@@ -79,7 +79,7 @@ ButtonComboModule_ControllerTypes ButtonComboInfoIF::getControllerMask() const {
7979

8080
void ButtonComboInfoIF::setControllerMask(const ButtonComboModule_ControllerTypes mask) {
8181
mControllerMask = mask;
82-
DEBUG_FUNCTION_LINE("Updated controllerMask to: %08X, for %s %08X", mControllerMask, mLabel.c_str(), getHandle().handle);
82+
DEBUG_FUNCTION_LINE("Updated controllerMask to: %08X, for %s handle: %p", mControllerMask, mLabel.c_str(), getHandle().handle);
8383
resetPrevInput();
8484
}
8585

@@ -97,6 +97,12 @@ bool ButtonComboInfoIF::conflictsWith(const ButtonComboModule_ButtonComboOptions
9797
if ((mControllerMask & other.controllerMask) == 0) {
9898
return false;
9999
}
100+
101+
// No conflicts when either button combo is empty.
102+
if (other.combo == 0 || mCombo == 0) {
103+
return false;
104+
}
105+
100106
if ((other.combo & mCombo) == mCombo || (other.combo & mCombo) == other.combo) {
101107
return true;
102108
}
@@ -141,4 +147,4 @@ int32_t ButtonComboInfoIF::ControllerTypeToChanIndex(const ButtonComboModule_Con
141147
}
142148

143149
return -1;
144-
}
150+
}

source/ButtonComboInfoDown.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ int ButtonComboInfoDown::UpdateInput(
3131

3232
auto &[prevButtonCombo] = mHoldInformation[chanIndex];
3333

34-
DEBUG_FUNCTION_LINE_VERBOSE("[PRESS DOWN] Check button combo %08X on controller %08X (lastItem im pressedButtons (size %d) is %08X) for %s [%08X]", mCombo, controller, pressedButtons.size(), pressedButtons.back(), mLabel.c_str(), getHandle().handle);
34+
DEBUG_FUNCTION_LINE_VERBOSE("[PRESS DOWN] Check button combo %08X on controller %08X (lastItem im pressedButtons (size %d) is %08X) for %s [%p]", mCombo, controller, pressedButtons.size(), pressedButtons.back(), mLabel.c_str(), getHandle().handle);
3535

3636
int activatedIndex = -1;
3737
for (auto [index, pressedButton] : std::views::enumerate(pressedButtons)) {
@@ -41,11 +41,11 @@ int ButtonComboInfoDown::UpdateInput(
4141

4242
if (buttonsPressedChanged && buttonsPressedMatchCombo && !prevButtonsIncludedCombo) {
4343
if (mCallback != nullptr) {
44-
DEBUG_FUNCTION_LINE("Calling callback [%08X](controller: %08X, context: %08X) for \"%s\" [handle: %08X], pressed down %08X", mCallback, controller, mContext, mLabel.c_str(), getHandle().handle, mCombo);
44+
DEBUG_FUNCTION_LINE("Calling callback [%p](controller: %08X, context: %p) for \"%s\" [handle: %p], pressed down %08X", mCallback, controller, mContext, mLabel.c_str(), getHandle().handle, mCombo);
4545
mCallback(controller, getHandle(), mContext);
4646
activatedIndex = index;
4747
} else {
48-
DEBUG_FUNCTION_LINE_WARN("Callback was null for combo %08X", getHandle());
48+
DEBUG_FUNCTION_LINE_WARN("Callback was null for combo %p", getHandle().handle);
4949
}
5050
}
5151
prevButtonCombo = pressedButton;

source/ButtonComboInfoHold.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ int ButtonComboInfoHold::UpdateInput(const ButtonComboModule_ControllerTypes con
3737
auto &holdInformation = mHoldInformation[chanIndex];
3838
const auto latestButtonPress = pressedButtons.back();
3939

40-
DEBUG_FUNCTION_LINE_VERBOSE("[HOLD ] Check button combo %08X on controller %08X (lastItem im pressedButtons (size %d) is %08X) for %s [%08X]", mCombo, controller, pressedButtons.size(), latestButtonPress, mLabel.c_str(), getHandle().handle);
40+
DEBUG_FUNCTION_LINE_VERBOSE("[HOLD ] Check button combo %08X on controller %08X (lastItem im pressedButtons (size %d) is %08X) for %s [%p]", mCombo, controller, pressedButtons.size(), latestButtonPress, mLabel.c_str(), getHandle().handle);
4141

4242
const bool prevButtonsIncludedCombo = (holdInformation.prevButtonCombo & mCombo) == mCombo; // Make sure the combo can't be triggered on releasing
4343
const bool buttonsPressedChanged = holdInformation.prevButtonCombo != latestButtonPress; // Avoid "holding" the combo
@@ -53,11 +53,11 @@ int ButtonComboInfoHold::UpdateInput(const ButtonComboModule_ControllerTypes con
5353

5454
if (intervalInMs > mTargetDurationInMs && !holdInformation.callbackTriggered) {
5555
if (mCallback != nullptr) {
56-
DEBUG_FUNCTION_LINE("Calling callback [%08X](controller: %08X context: %08X) for \"%s\" [handle: %08X], hold %08X for %d ms", mCallback, controller, mContext, mLabel.c_str(), getHandle().handle, mCombo, intervalInMs);
56+
DEBUG_FUNCTION_LINE("Calling callback [%p](controller: %08X context: %p) for \"%s\" [handle: %p], hold %08X for %d ms", mCallback, controller, mContext, mLabel.c_str(), getHandle().handle, mCombo, intervalInMs);
5757
mCallback(controller, getHandle(), mContext);
5858
activatedIndex = pressedButtons.size() - 1;
5959
} else {
60-
DEBUG_FUNCTION_LINE_WARN("Callback was null for combo %08X", getHandle());
60+
DEBUG_FUNCTION_LINE_WARN("Callback was null for combo %p", getHandle().handle);
6161
}
6262
holdInformation.callbackTriggered = true;
6363
}
@@ -69,7 +69,7 @@ int ButtonComboInfoHold::UpdateInput(const ButtonComboModule_ControllerTypes con
6969
}
7070

7171
ButtonComboModule_Error ButtonComboInfoHold::setHoldDuration(const uint32_t holdDurationInMs) {
72-
DEBUG_FUNCTION_LINE("Setting holdDurationInMs to %d for %s [%08X]", holdDurationInMs, mLabel.c_str(), getHandle().handle);
72+
DEBUG_FUNCTION_LINE("Setting holdDurationInMs to %d for %s [%p]", holdDurationInMs, mLabel.c_str(), getHandle().handle);
7373
mTargetDurationInMs = holdDurationInMs;
7474
return BUTTON_COMBO_MODULE_ERROR_SUCCESS;
7575
}

0 commit comments

Comments
 (0)