Block screenshots of the Gamepad if it's not connected

This commit is contained in:
Maschell 2023-01-26 13:01:46 +01:00
parent 0ba843dab7
commit dbd48c757f
7 changed files with 98 additions and 3 deletions

67
src/DRCAttachCallback.cpp Normal file
View File

@ -0,0 +1,67 @@
#include "DRCAttachCallback.h"
#include "retain_vars.hpp"
#include "utils/logger.h"
#include <coreinit/cache.h>
#include <map>
#include <mutex>
#include <wups.h>
std::mutex gDRCCallbackMutex;
CCRCDCCallbackData gCCRCDCCallbackDataCurrent;
std::map<CCRCDCCallbackDataCallback, void *> gDRCCallbackData;
void DRCAttachDetachCallbackWrapper(CCRCDCCallbackData *data, void *context) {
std::lock_guard<std::mutex> lock(gDRCCallbackMutex);
// Callbacks get called when added, so we need to save the current "data" and then pass it to newly added callbacks
memcpy(&gCCRCDCCallbackDataCurrent, data, sizeof(CCRCDCCallbackData));
// Call all callbacks.
for (auto &cur : gDRCCallbackData) {
if (cur.first != nullptr) {
cur.first(data, cur.second);
}
}
}
/**
* From what I can tell `CCRCDCRegisterUVCAttachCallback` is never used by any .rpl/.rpx
* Let's add multiple for multiple callbacks anyway, better safe than sorry.
*/
DECL_FUNCTION(void, CCRCDCRegisterUVCAttachCallback, CCRCDCCallbackDataCallback callback, void *context) {
std::lock_guard<std::mutex> lock(gDRCCallbackMutex);
if (callback == nullptr && context == nullptr) { // Delete (all) callbacks.
real_CCRCDCRegisterUVCAttachCallback(callback, context);
gDRCCallbackData.clear();
return;
}
if (callback != nullptr) {
// Add callback
gDRCCallbackData[callback] = context;
// Call callback
callback(&gCCRCDCCallbackDataCurrent, context);
}
}
WUPS_MUST_REPLACE(CCRCDCRegisterUVCAttachCallback, WUPS_LOADER_LIBRARY_NSYSCCR, CCRCDCRegisterUVCAttachCallback);
void DRCAttachDetachCallback(CCRCDCCallbackData *data, void *context) {
gBlockDRCScreenshots = !data->attached;
if (!data->attached) {
DEBUG_FUNCTION_LINE("Block DRC screenshots");
}
OSMemoryBarrier();
}
extern "C" int CCRCDCRegisterUVCAttachCallback(void (*)(CCRCDCCallbackData *, void *), void *);
void InitDRCAttachCallbacks() {
// Clear existing callbacks
gDRCCallbackData.clear();
// Add wrapper function to support multiple callbacks.
real_CCRCDCRegisterUVCAttachCallback(DRCAttachDetachCallbackWrapper, nullptr);
// Add the real callback we want to use.
CCRCDCRegisterUVCAttachCallback(DRCAttachDetachCallback, nullptr);
}

14
src/DRCAttachCallback.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#include <vpad/input.h>
#include <wut.h>
struct WUT_PACKED CCRCDCCallbackData {
uint32_t attached;
VPADChan chan;
WUT_UNKNOWN_BYTES(6);
};
extern CCRCDCCallbackData gCCRCDCCallbackDataCurrent;
typedef void (*CCRCDCCallbackDataCallback)(CCRCDCCallbackData *, void *);
void InitDRCAttachCallbacks();

View File

@ -93,7 +93,6 @@ void InitConfig() {
} }
} }
void multipleValueItemCallback(ConfigItemMultipleValues *item, uint32_t newValue) { void multipleValueItemCallback(ConfigItemMultipleValues *item, uint32_t newValue) {
if (item && item->configId) { if (item && item->configId) {
DEBUG_FUNCTION_LINE("New value in %s changed: %d", item->configId, newValue); DEBUG_FUNCTION_LINE("New value in %s changed: %d", item->configId, newValue);

View File

@ -59,6 +59,10 @@ void RequestScreenshot() {
} }
} }
if (gImageSource == IMAGE_SOURCE_TV_AND_DRC || gImageSource == IMAGE_SOURCE_DRC) { if (gImageSource == IMAGE_SOURCE_TV_AND_DRC || gImageSource == IMAGE_SOURCE_DRC) {
if (gBlockDRCScreenshots) {
DEBUG_FUNCTION_LINE("Screenshots are blocked for DRC because it's not connected");
return;
}
if (gTakeScreenshotDRC == SCREENSHOT_STATE_READY) { if (gTakeScreenshotDRC == SCREENSHOT_STATE_READY) {
DEBUG_FUNCTION_LINE("Requested screenshot for DRC!"); DEBUG_FUNCTION_LINE("Requested screenshot for DRC!");
gTakeScreenshotDRC = SCREENSHOT_STATE_REQUESTED; gTakeScreenshotDRC = SCREENSHOT_STATE_REQUESTED;

View File

@ -1,4 +1,5 @@
#include "main.h" #include "main.h"
#include "DRCAttachCallback.h"
#include "config.h" #include "config.h"
#include "retain_vars.hpp" #include "retain_vars.hpp"
#include "thread.h" #include "thread.h"
@ -35,6 +36,10 @@ DEINITIALIZE_PLUGIN() {
NotificationModule_DeInitLibrary(); NotificationModule_DeInitLibrary();
} }
ON_ACQUIRED_FOREGROUND() {
InitDRCAttachCallbacks();
}
// Called whenever an application was started. // Called whenever an application was started.
ON_APPLICATION_START() { ON_APPLICATION_START() {
initLogging(); initLogging();
@ -45,6 +50,8 @@ ON_APPLICATION_START() {
ApplyGameSpecificPatches(); ApplyGameSpecificPatches();
VPADSetTVMenuInvalid(VPAD_CHAN_0, true); VPADSetTVMenuInvalid(VPAD_CHAN_0, true);
InitDRCAttachCallbacks();
} }
ON_APPLICATION_REQUESTS_EXIT() { ON_APPLICATION_REQUESTS_EXIT() {

View File

@ -21,4 +21,6 @@ bool gNotAvailableNotificationDisplayed = false;
NMColor COLOR_RED = {237, 28, 36, 255}; NMColor COLOR_RED = {237, 28, 36, 255};
int32_t gThreadPriorityIncrease = 1; int32_t gThreadPriorityIncrease = 1;
bool gBlockDRCScreenshots = false;

View File

@ -24,4 +24,6 @@ extern bool gNotAvailableNotificationDisplayed;
extern NMColor COLOR_RED; extern NMColor COLOR_RED;
extern int32_t gThreadPriorityIncrease; extern int32_t gThreadPriorityIncrease;
extern bool gBlockDRCScreenshots;