#include "DRCAttachCallback.h" #include "retain_vars.hpp" #include "utils/logger.h" #include #include #include #include std::mutex gDRCCallbackMutex; CCRCDCCallbackData gCCRCDCCallbackDataCurrent; std::map gDRCCallbackData; void DRCAttachDetachCallbackWrapper(CCRCDCCallbackData *data, void *context) { std::lock_guard 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 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); }