Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 6 additions & 11 deletions source/ButtonComboManager.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "ButtonComboManager.h"
#include "ButtonComboInfoDown.h"
#include "ButtonComboInfoHold.h"
#include "TVOverlayManager.h"
#include "logger.h"

#include <buttoncombo/defines.h>
Expand Down Expand Up @@ -335,7 +336,7 @@ std::optional<std::shared_ptr<ButtonComboInfoIF>> ButtonComboManager::CreateComb

bool ButtonComboManager::hasActiveComboWithTVButton() {
std::lock_guard lock(mMutex);
return std::ranges::any_of(mCombos, [](const auto &combo) { return combo->getStatus() == BUTTON_COMBO_MODULE_COMBO_STATUS_VALID && combo->getCombo() & BCMPAD_BUTTON_TV; });
return std::ranges::any_of(mCombos, [](const auto &combo) { return combo->getStatus() == BUTTON_COMBO_MODULE_COMBO_STATUS_VALID && combo->getCombo() & BCMPAD_BUTTON_TV && !combo->isObserver(); });
}

ButtonComboModule_ComboStatus ButtonComboManager::CheckComboStatus(const ButtonComboInfoIF &other) {
Expand Down Expand Up @@ -363,7 +364,7 @@ void ButtonComboManager::AddCombo(std::shared_ptr<ButtonComboInfoIF> newComboInf
outHandle = newComboInfo->getHandle();
mCombos.emplace_front(std::move(newComboInfo));

UpdateTVMenuBlocking();
TVOverlayManager::UpdateBlocking();
}

ButtonComboModule_Error ButtonComboManager::RemoveCombo(ButtonComboModule_ComboHandle handle) {
Expand All @@ -377,7 +378,7 @@ ButtonComboModule_Error ButtonComboManager::RemoveCombo(ButtonComboModule_ComboH
if (!remove_first_if(mCombos, [handle](const auto &combo) { return combo->getHandle() == handle; })) {
DEBUG_FUNCTION_LINE_WARN("Failed to remove combo by handle %p", handle.handle);
} else {
UpdateTVMenuBlocking();
TVOverlayManager::UpdateBlocking();
}

return BUTTON_COMBO_MODULE_ERROR_SUCCESS;
Expand Down Expand Up @@ -432,12 +433,6 @@ void ButtonComboManager::UpdateInputVPAD(const VPADChan chan, const VPADStatus *
}
}

void ButtonComboManager::UpdateTVMenuBlocking() {
const auto block = hasActiveComboWithTVButton();
VPADSetTVMenuInvalid(VPAD_CHAN_0, block);
VPADSetTVMenuInvalid(VPAD_CHAN_1, block);
}

void ButtonComboManager::UpdateInputsLocked(const ButtonComboModule_ControllerTypes controller, const std::span<uint32_t> pressedButtons) {
std::lock_guard lock(mMutex);
mIsIterating++;
Expand All @@ -457,7 +452,7 @@ void ButtonComboManager::UpdateInputsLocked(const ButtonComboModule_ControllerTy
mCombosToRemove.clear();

// Update TV Menu blocking status once after all removals
UpdateTVMenuBlocking();
TVOverlayManager::UpdateBlocking();
}
}

Expand Down Expand Up @@ -569,7 +564,7 @@ ButtonComboModule_Error ButtonComboManager::UpdateButtonCombo(const ButtonComboM
comboInfo->setStatus(CheckComboStatus(*comboInfo));
outComboStatus = comboInfo->getStatus();

UpdateTVMenuBlocking();
TVOverlayManager::UpdateBlocking();

return BUTTON_COMBO_MODULE_ERROR_SUCCESS;
}
Expand Down
3 changes: 1 addition & 2 deletions source/ButtonComboManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ class ButtonComboManager {
static std::optional<std::shared_ptr<ButtonComboInfoIF>> CreateComboInfo(const ButtonComboModule_ComboOptions &options, ButtonComboModule_Error &err);

void UpdateInputVPAD(VPADChan chan, const VPADStatus *buffer, uint32_t bufferSize, const VPADReadError *error);
void UpdateTVMenuBlocking();

void UpdateInputWPAD(WPADChan chan, WPADStatus *data);

Expand Down Expand Up @@ -66,4 +65,4 @@ class ButtonComboManager {
mutable std::recursive_mutex mMutex;
std::recursive_mutex mDetectButtonsMutex;
bool mInButtonComboDetection = false;
};
};
115 changes: 115 additions & 0 deletions source/TVOverlayManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#include "TVOverlayManager.h"
#include "ButtonComboManager.h"
#include "export.h"
#include "globals.h"
#include "logger.h"

#include <coreinit/cache.h>
#include <coreinit/debug.h>
#include <coreinit/time.h>

namespace TVOverlayManager {

namespace {

ButtonComboModule_ComboHandle sTVButtonHandle;
// Track when the TV button was last pressed to implement timeout, or zero if
// timeout expired.
OSTime sTVPressed[2];
bool sTVMenuBlocked[2];

void TVComboCallback(ButtonComboModule_ControllerTypes triggeredBy,
ButtonComboModule_ComboHandle,
void *) {
VPADChan chan;
switch (triggeredBy) {
case BUTTON_COMBO_MODULE_CONTROLLER_VPAD_0:
chan = VPAD_CHAN_0;
break;
case BUTTON_COMBO_MODULE_CONTROLLER_VPAD_1:
chan = VPAD_CHAN_1;
break;
default:
return;
}
DEBUG_FUNCTION_LINE_INFO("TV pressed");
sTVPressed[chan] = OSGetSystemTime();
OSMemoryBarrier();
}

void SetBlocked(VPADChan channel, bool blocked) {
VPADSetTVMenuInvalid(channel, blocked);
sTVMenuBlocked[channel] = blocked;
}

} // namespace

void RegisterCombo() {
ButtonComboModule_ComboOptions opt = {};
opt.version = BUTTON_COMBO_MODULE_COMBO_OPTIONS_VERSION;
opt.metaOptions.label = "TV remote overlay combo";
opt.callbackOptions.callback = TVComboCallback;
opt.callbackOptions.context = {};
opt.buttonComboOptions.type = BUTTON_COMBO_MODULE_COMBO_TYPE_PRESS_DOWN_OBSERVER;
opt.buttonComboOptions.basicCombo.combo = BCMPAD_BUTTON_TV;
opt.buttonComboOptions.basicCombo.controllerMask = BUTTON_COMBO_MODULE_CONTROLLER_VPAD;
opt.buttonComboOptions.optionalHoldForXMs = 0;
if (ButtonComboModule_AddButtonCombo(&opt, &sTVButtonHandle, nullptr) != BUTTON_COMBO_MODULE_ERROR_SUCCESS) {
DEBUG_FUNCTION_LINE_ERR("FAILED TO SET UP TV COMBO!");
}
}

void UnregisterCombo() {
ButtonComboModule_RemoveButtonCombo(sTVButtonHandle);
}

void InitVPAD(VPADChan channel) {
bool blocked = false;
if (auto mgr = gButtonComboManager) {
blocked = mgr->hasActiveComboWithTVButton();
}
SetBlocked(channel, blocked);
ResetVPAD(channel);
}

void ResetVPAD(VPADChan channel) {
sTVPressed[channel] = 0;
OSMemoryBarrier();
}

void UpdateVPAD(VPADChan channel) {
if (sTVPressed[channel]) {
OSTime elapsed = OSGetSystemTime() - sTVPressed[channel];
// TODO: this should be configurable by the public API.
const OSTime double_press_time = OSMillisecondsToTicks(100);
if (elapsed > double_press_time && sTVMenuBlocked[channel]) {
DEBUG_FUNCTION_LINE_INFO("Unblocking TV menu");
SetBlocked(channel, false);
}
// TODO: this should be configurable by the public API.
const OSTime tv_enable_timeout = OSMillisecondsToTicks(1000);
if (elapsed > tv_enable_timeout && !VPADGetTVMenuStatus(channel)) {
bool blocked = false;
if (auto mgr = gButtonComboManager) {
blocked = mgr->hasActiveComboWithTVButton();
}
DEBUG_FUNCTION_LINE_INFO("TV timeout reached, setting TV Menu block to %s",
blocked ? "blocked" : "unblocked");
SetBlocked(channel, blocked);
ResetVPAD(channel);
}
}
}

void UpdateBlocking() {
bool blocked = false;
if (auto mgr = gButtonComboManager) {
blocked = mgr->hasActiveComboWithTVButton();
}
for (VPADChan channel : {VPAD_CHAN_0, VPAD_CHAN_1}) {
SetBlocked(channel, blocked);
ResetVPAD(channel);
}
}

} // namespace TVOverlayManager
20 changes: 20 additions & 0 deletions source/TVOverlayManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include <vpad/input.h>

namespace TVOverlayManager
{

void RegisterCombo();

void UnregisterCombo();

void InitVPAD(VPADChan channel);

void ResetVPAD(VPADChan channel);

void UpdateVPAD(VPADChan channel);

void UpdateBlocking();

} // namespace TVOverlayManager
1 change: 1 addition & 0 deletions source/export.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "export.h"
#include "ButtonComboManager.h"
#include "globals.h"

Expand Down
9 changes: 9 additions & 0 deletions source/export.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <buttoncombo/defines.h>

extern ButtonComboModule_Error ButtonComboModule_AddButtonCombo(const ButtonComboModule_ComboOptions *options,
ButtonComboModule_ComboHandle *outHandle,
ButtonComboModule_ComboStatus *outStatus);

extern ButtonComboModule_Error ButtonComboModule_RemoveButtonCombo(const ButtonComboModule_ComboHandle handle);
18 changes: 12 additions & 6 deletions source/function_patches.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "ButtonComboInfo.h"
#include "ButtonComboManager.h"
#include "TVOverlayManager.h"
#include "globals.h"

#include <function_patcher/fpatching_defines.h>
Expand All @@ -13,23 +14,27 @@ DECL_FUNCTION(int32_t, VPADRead, VPADChan chan, VPADStatus *buffer, uint32_t buf
const int32_t result = real_VPADRead(chan, buffer, buffer_size, &real_error);

if (result > 0 && real_error == VPAD_READ_SUCCESS) {
if (const auto comboManager = gButtonComboManager; comboManager) {
if (const auto comboManager = gButtonComboManager) {
comboManager->UpdateInputVPAD(chan, buffer, result > static_cast<int32_t>(buffer_size) ? buffer_size : result, error);
}
}
if (error) {
*error = real_error;
}

TVOverlayManager::UpdateVPAD(chan);

return result;
}

DECL_FUNCTION(void, WPADRead, WPADChan chan, WPADStatus *data) {
real_WPADRead(chan, data);

if (const auto comboManager = gButtonComboManager; comboManager) {
if (const auto comboManager = gButtonComboManager) {
comboManager->UpdateInputWPAD(chan, data);
}
}

struct WUT_PACKED CCRCDCCallbackData {
uint32_t attached;
VPADChan chan;
Expand All @@ -39,10 +44,11 @@ struct WUT_PACKED CCRCDCCallbackData {
DECL_FUNCTION(void, __VPADBASEAttachCallback, CCRCDCCallbackData *data, void *context) {
real___VPADBASEAttachCallback(data, context);

if (data && data->attached) {
if (const auto comboManager = gButtonComboManager; comboManager) {
const bool block = comboManager->hasActiveComboWithTVButton();
VPADSetTVMenuInvalid(data->chan, block);
if (data) {
if (data->attached) {
TVOverlayManager::InitVPAD(data->chan);
} else {
TVOverlayManager::ResetVPAD(data->chan);
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions source/main.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "ButtonComboManager.h"
#include "TVOverlayManager.h"
#include "function_patches.h"
#include "globals.h"
#include "logger.h"
Expand Down Expand Up @@ -34,10 +35,13 @@ WUMS_INITIALIZE() {

gButtonComboManager = std::make_unique<ButtonComboManager>();

TVOverlayManager::RegisterCombo();

deinitLogging();
}

WUMS_DEINITIALIZE() {
TVOverlayManager::UnregisterCombo();
gButtonComboManager.reset();
}

Expand Down