From 74056b148118b2479be23db2441b86bef2c2d8db Mon Sep 17 00:00:00 2001 From: Maschell Date: Sun, 3 Mar 2024 18:04:14 +0100 Subject: [PATCH] Add support for mirroring the TV/DRC --- src/function_patcher.cpp | 66 ++++++++++++++++++++++++++++++++++------ src/main.cpp | 33 +++++++++++++++----- src/retain_vars.cpp | 5 +-- src/retain_vars.hpp | 11 ++++++- src/utils/config.cpp | 24 ++++++++++----- src/utils/config.h | 6 ++-- src/utils/logger.h | 2 ++ 7 files changed, 117 insertions(+), 30 deletions(-) diff --git a/src/function_patcher.cpp b/src/function_patcher.cpp index 9bdfd0e..c1cd048 100644 --- a/src/function_patcher.cpp +++ b/src/function_patcher.cpp @@ -29,12 +29,36 @@ void UpdateAudioMode(); DECL_FUNCTION(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer *colorBuffer, GX2ScanTarget scan_target) { - if (gEnabled && gDoScreenSwap) { - if (scan_target == GX2_SCAN_TARGET_TV) { - scan_target = GX2_SCAN_TARGET_DRC; - } else if (scan_target == GX2_SCAN_TARGET_DRC) { - scan_target = GX2_SCAN_TARGET_TV; + if (gEnabled && gCurScreenMode != SCREEN_MODE_NONE) { + switch (gCurScreenMode) { + case SCREEN_MODE_SWAP: { + if (scan_target == GX2_SCAN_TARGET_TV) { + scan_target = GX2_SCAN_TARGET_DRC; + } else if (scan_target == GX2_SCAN_TARGET_DRC) { + scan_target = GX2_SCAN_TARGET_TV; + } + break; + } + case SCREEN_MODE_MIRROR_TV: { + if (scan_target == GX2_SCAN_TARGET_TV) { + scan_target = GX2_SCAN_TARGET_TV | GX2_SCAN_TARGET_DRC; + } else if (scan_target == GX2_SCAN_TARGET_DRC) { + return; + } + break; + } + case SCREEN_MODE_MIRROR_DRC: { + if (scan_target == GX2_SCAN_TARGET_DRC) { + scan_target = GX2_SCAN_TARGET_TV | GX2_SCAN_TARGET_DRC; + } else if (scan_target == GX2_SCAN_TARGET_TV) { + return; + } + break; + } + default: + break; } + if (colorBuffer->surface.aa != GX2_AA_MODE1X) { // If AA is enabled, we need to resolve the AA buffer. GX2Surface tempSurface; @@ -66,10 +90,14 @@ DECL_FUNCTION(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer *colorBuffer, } void SwapScreens() { - gDoScreenSwap = !gDoScreenSwap; + if (gCurScreenMode == SCREEN_MODE_SWAP) { + gCurScreenMode = SCREEN_MODE_NONE; + } else { + gCurScreenMode = SCREEN_MODE_SWAP; + } if (gShowNotifications && gNotificationModuleInitDone) { - if (gDoScreenSwap) { + if (gCurScreenMode) { NotificationModule_AddInfoNotification("Swapping TV and GamePad screen"); } else { NotificationModule_AddInfoNotification("Stop swapping TV and GamePad screen"); @@ -188,9 +216,27 @@ void DoAudioMagic(int16_t *addr, uint32_t size, bool isDRC, AIInitDMAfn targetFu otherFunc(addr, sizeCpy); return; case AUDIO_MODE_MATCH_SCREEN: { - if (gDoScreenSwap) { - otherFunc(addr, sizeCpy); - return; + switch (gCurScreenMode) { + case SCREEN_MODE_SWAP: + otherFunc(addr, sizeCpy); + return; + case SCREEN_MODE_MIRROR_TV: + case SCREEN_MODE_MIRROR_DRC: { + if (isDRC) { + memcpy(DRCCopy, addr, sizeCpy); + } else { + memcpy(TVCopy, addr, sizeCpy); + } + if (gCurScreenMode == SCREEN_MODE_MIRROR_TV) { + memcpy(addr, TVCopy, sizeCpy); + } else if (gCurScreenMode == SCREEN_MODE_MIRROR_DRC) { + memcpy(addr, DRCCopy, sizeCpy); + } + break; + } + case SCREEN_MODE_NONE: + case SCREEN_MODE_MAX_VALUE: + break; } break; } diff --git a/src/main.cpp b/src/main.cpp index eb9ad94..ceeda6f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,6 +34,19 @@ WUPS_USE_WUT_DEVOPTAB(); WUPS_USE_STORAGE("SwipSwapMeAroma"); +void migrateStorage() { + uint32_t doSwap = false; + if (WUPSStorageAPI_GetU32(nullptr, SWAP_SCREENS_CONFIG_STRING_DEPRECATED, &doSwap) == WUPS_STORAGE_ERROR_SUCCESS) { + DEBUG_FUNCTION_LINE_INFO("Found deprecated config in storage. Storage will be migrated"); + if (doSwap) { + gCurScreenMode = SCREEN_MODE_SWAP; + } + if (WUPSStorageAPI_DeleteItem(nullptr, SWAP_SCREENS_CONFIG_STRING_DEPRECATED) != WUPS_STORAGE_ERROR_SUCCESS) { + DEBUG_FUNCTION_LINE_WARN("Failed to delete deprecated value: \"%s\" from storage", SWAP_SCREENS_CONFIG_STRING_DEPRECATED); + } + } +} + // Gets called once the loader exists. INITIALIZE_PLUGIN() { initLogging(); @@ -45,12 +58,15 @@ INITIALIZE_PLUGIN() { DEBUG_FUNCTION_LINE_ERR("Failed to init notification lib"); } + gCurScreenMode = DEFAULT_SCREEN_MODE_CONFIG_VALUE; // migrateStorage might override this + migrateStorage(); + WUPSStorageError err; if ((err = WUPSStorageAPI::GetOrStoreDefault(ENABLED_CONFIG_STRING, gEnabled, DEFAULT_ENABLED_CONFIG_VALUE)) != WUPS_STORAGE_ERROR_SUCCESS) { DEBUG_FUNCTION_LINE_ERR("Failed to get or create item \"%s\": %s (%d)", ENABLED_CONFIG_STRING, WUPSStorageAPI_GetStatusStr(err), err); } - if ((err = WUPSStorageAPI::GetOrStoreDefault(SWAP_SCREENS_CONFIG_STRING, gDoScreenSwap, DEFAULT_SWAP_SCREENS_CONFIG_VALUE)) != WUPS_STORAGE_ERROR_SUCCESS) { - DEBUG_FUNCTION_LINE_ERR("Failed to get or create item \"%s\": %s (%d)", SWAP_SCREENS_CONFIG_STRING, WUPSStorageAPI_GetStatusStr(err), err); + if ((err = WUPSStorageAPI::GetOrStoreDefault(SCREEN_MODE_CONFIG_STRING, gCurScreenMode, gCurScreenMode)) != WUPS_STORAGE_ERROR_SUCCESS) { + DEBUG_FUNCTION_LINE_ERR("Failed to get or create item \"%s\": %s (%d)", SCREEN_MODE_CONFIG_STRING, WUPSStorageAPI_GetStatusStr(err), err); } if ((err = WUPSStorageAPI::GetOrStoreDefault(ENABLED_SWAP_SCREENS_COMBO_CONFIG_STRING, gSwapScreenButtonComboEnabled, DEFAULT_ENABLED_SWAP_SCREENS_COMBO_CONFIG_VALUE)) != WUPS_STORAGE_ERROR_SUCCESS) { DEBUG_FUNCTION_LINE_ERR("Failed to get or create item \"%s\": %s (%d)", ENABLED_SWAP_SCREENS_COMBO_CONFIG_STRING, WUPSStorageAPI_GetStatusStr(err), err); @@ -91,24 +107,25 @@ DEINITIALIZE_PLUGIN() { } } -SwipSwapAudioMode sAudioModeAtStart; -bool sDoSwapAtStart; +static SwipSwapAudioMode sAudioModeAtStart; +static SwipSwapScreenMode sScreenModeAtStart; // Called whenever an application was started. ON_APPLICATION_START() { initLogging(); - sAudioModeAtStart = gCurAudioMode; - sDoSwapAtStart = gDoScreenSwap; + + sAudioModeAtStart = gCurAudioMode; + sScreenModeAtStart = gCurScreenMode; } ON_APPLICATION_REQUESTS_EXIT() { - if (sAudioModeAtStart != gCurAudioMode || sDoSwapAtStart != gDoScreenSwap) { + if (sAudioModeAtStart != gCurAudioMode || sScreenModeAtStart != gCurScreenMode) { WUPSStorageError err; if ((err = WUPSStorageAPI::Store(AUDIO_MODE_CONFIG_STRING, gCurAudioMode)) != WUPS_STORAGE_ERROR_SUCCESS) { DEBUG_FUNCTION_LINE_ERR("Failed to store audio mode to storage: %s (%d)", WUPSStorageAPI_GetStatusStr(err), err); } - if ((err = WUPSStorageAPI::Store(SWAP_SCREENS_CONFIG_STRING, gDoScreenSwap)) != WUPS_STORAGE_ERROR_SUCCESS) { + if ((err = WUPSStorageAPI::Store(SCREEN_MODE_CONFIG_STRING, gCurScreenMode)) != WUPS_STORAGE_ERROR_SUCCESS) { DEBUG_FUNCTION_LINE_ERR("Failed to store screen mode to storage: %s (%d)", WUPSStorageAPI_GetStatusStr(err), err); } if ((err = WUPSStorageAPI::SaveStorage()) != WUPS_STORAGE_ERROR_SUCCESS) { diff --git a/src/retain_vars.cpp b/src/retain_vars.cpp index d6dfa51..c888768 100644 --- a/src/retain_vars.cpp +++ b/src/retain_vars.cpp @@ -2,12 +2,13 @@ #include "utils/config.h" bool gEnabled = DEFAULT_ENABLED_CONFIG_VALUE; -bool gDoScreenSwap = DEFAULT_SWAP_SCREENS_CONFIG_VALUE; uint32_t gSwapScreenButtonCombo = DEFAULT_SWAP_SCREEN_BUTTON_COMBO_CONFIG_VALUE; uint32_t gSwapAudioButtonCombo = DEFAULT_CHANGE_AUDIO_BUTTON_COMBO_CONFIG_VALUE; bool gSwapScreenButtonComboEnabled = DEFAULT_ENABLED_SWAP_SCREENS_COMBO_CONFIG_VALUE; bool gChangeAudioModeButtonComboEnabled = DEFAULT_ENABLED_CHANGE_AUDIO_COMBO_CONFIG_VALUE; bool gShowNotifications = DEFAULT_ENABLE_NOTIFICATIONS_CONFIG_VALUE; -SwipSwapAudioMode gCurAudioMode = DEFAULT_AUDIO_MODE_CONFIG_VALUE; + +SwipSwapScreenMode gCurScreenMode = DEFAULT_SCREEN_MODE_CONFIG_VALUE; +SwipSwapAudioMode gCurAudioMode = DEFAULT_AUDIO_MODE_CONFIG_VALUE; bool gNotificationModuleInitDone = true; \ No newline at end of file diff --git a/src/retain_vars.hpp b/src/retain_vars.hpp index 08f06c5..1859e37 100644 --- a/src/retain_vars.hpp +++ b/src/retain_vars.hpp @@ -11,12 +11,21 @@ typedef enum SwipSwapAudioMode { AUDIO_MODE_MAX_VALUE = 5 } SwipSwapAudioMode; +typedef enum SwipSwapScreenMode { + SCREEN_MODE_NONE = 0, + SCREEN_MODE_SWAP = 1, + SCREEN_MODE_MIRROR_TV = 2, + SCREEN_MODE_MIRROR_DRC = 3, + SCREEN_MODE_MAX_VALUE = 4 +} SwipSwapScreenMode; + extern uint32_t gSwapScreenButtonCombo; extern uint32_t gSwapAudioButtonCombo; extern bool gSwapScreenButtonComboEnabled; extern bool gChangeAudioModeButtonComboEnabled; extern bool gEnabled; -extern bool gDoScreenSwap; extern bool gShowNotifications; extern bool gNotificationModuleInitDone; + +extern SwipSwapScreenMode gCurScreenMode; extern SwipSwapAudioMode gCurAudioMode; \ No newline at end of file diff --git a/src/utils/config.cpp b/src/utils/config.cpp index b91994d..0a89d17 100644 --- a/src/utils/config.cpp +++ b/src/utils/config.cpp @@ -15,8 +15,6 @@ static void boolItemChangedConfig(ConfigItemBoolean *item, bool newValue) { if (std::string_view(ENABLED_CONFIG_STRING) == item->identifier) { gEnabled = newValue; UpdateAudioMode(); - } else if (std::string_view(SWAP_SCREENS_CONFIG_STRING) == item->identifier) { - gDoScreenSwap = newValue; } else if (std::string_view(ENABLED_SWAP_SCREENS_COMBO_CONFIG_STRING) == item->identifier) { gSwapScreenButtonComboEnabled = newValue; } else if (std::string_view(ENABLED_CHANGE_AUDIO_COMBO_CONFIG_STRING) == item->identifier) { @@ -63,6 +61,8 @@ static void multiItemChanged(ConfigItemMultipleValues *item, uint32_t newValue) if (std::string_view(AUDIO_MODE_CONFIG_STRING) == item->identifier) { gCurAudioMode = static_cast(newValue); + } else if (std::string_view(SCREEN_MODE_CONFIG_STRING) == item->identifier) { + gCurScreenMode = static_cast(newValue); } else { DEBUG_FUNCTION_LINE_WARN("Unexpected button combo item: %s", item->identifier); return; @@ -86,10 +86,20 @@ WUPSConfigAPICallbackStatus ConfigMenuOpenedCallback(WUPSConfigCategoryHandle ro "Show notifications", DEFAULT_ENABLE_NOTIFICATIONS_CONFIG_VALUE, gShowNotifications, &boolItemChangedConfig)); - root.add(WUPSConfigItemBoolean::Create(SWAP_SCREENS_CONFIG_STRING, - "Swap screens", - DEFAULT_SWAP_SCREENS_CONFIG_VALUE, gDoScreenSwap, - &boolItemChangedConfig)); + + + constexpr WUPSConfigItemMultipleValues::ValuePair screenModeMap[] = { + {SCREEN_MODE_NONE, "Normal"}, + {SCREEN_MODE_SWAP, "Swap TV and GamePad"}, + {SCREEN_MODE_MIRROR_TV, "Mirror TV"}, + {SCREEN_MODE_MIRROR_DRC, "Mirror DRC"}, + }; + + root.add(WUPSConfigItemMultipleValues::CreateFromValue(SCREEN_MODE_CONFIG_STRING, + "Screen mode:", + DEFAULT_SCREEN_MODE_CONFIG_VALUE, gCurScreenMode, + screenModeMap, + &multiItemChanged)); constexpr WUPSConfigItemMultipleValues::ValuePair audioModeMap[] = { {AUDIO_MODE_NONE, "Normal"}, @@ -107,7 +117,7 @@ WUPSConfigAPICallbackStatus ConfigMenuOpenedCallback(WUPSConfigCategoryHandle ro auto buttonCombos = WUPSConfigCategory::Create("Button Combos"); buttonCombos.add(WUPSConfigItemBoolean::Create(ENABLED_SWAP_SCREENS_COMBO_CONFIG_STRING, - "Enable swap screen button combo", + "Enable change swap screen button combo", DEFAULT_ENABLED_SWAP_SCREENS_COMBO_CONFIG_VALUE, gSwapScreenButtonComboEnabled, &boolItemChangedConfig)); diff --git a/src/utils/config.h b/src/utils/config.h index 2eb6c17..c24e2ca 100644 --- a/src/utils/config.h +++ b/src/utils/config.h @@ -7,16 +7,18 @@ #include #define DEFAULT_ENABLED_CONFIG_VALUE true -#define DEFAULT_SWAP_SCREENS_CONFIG_VALUE false #define DEFAULT_ENABLED_SWAP_SCREENS_COMBO_CONFIG_VALUE true #define DEFAULT_ENABLED_CHANGE_AUDIO_COMBO_CONFIG_VALUE false #define DEFAULT_ENABLE_NOTIFICATIONS_CONFIG_VALUE true #define DEFAULT_SWAP_SCREEN_BUTTON_COMBO_CONFIG_VALUE VPAD_BUTTON_TV #define DEFAULT_CHANGE_AUDIO_BUTTON_COMBO_CONFIG_VALUE VPAD_BUTTON_STICK_L + +#define DEFAULT_SCREEN_MODE_CONFIG_VALUE SCREEN_MODE_NONE #define DEFAULT_AUDIO_MODE_CONFIG_VALUE AUDIO_MODE_MATCH_SCREEN #define ENABLED_CONFIG_STRING "enabled" -#define SWAP_SCREENS_CONFIG_STRING "swapScreens" +#define SWAP_SCREENS_CONFIG_STRING_DEPRECATED "swapScreens" +#define SCREEN_MODE_CONFIG_STRING "screenMode" #define ENABLED_SWAP_SCREENS_COMBO_CONFIG_STRING "swapScreensComboEnabled" #define ENABLED_CHANGE_AUDIO_COMBO_CONFIG_STRING "changeAudioComboEnabled" #define ENABLE_NOTIFICATIONS_CONFIG_STRING "notificationsEnabled" diff --git a/src/utils/logger.h b/src/utils/logger.h index e1b18f6..5c399dd 100644 --- a/src/utils/logger.h +++ b/src/utils/logger.h @@ -39,6 +39,7 @@ extern "C" { #define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX_DEFAULT(WHBLogPrintf, "##ERROR## ", "", FMT, ##ARGS) #define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX_DEFAULT(WHBLogPrintf, "##WARN ## ", "", FMT, ##ARGS) +#define DEBUG_FUNCTION_LINE_INFO(FMT, ARGS...) LOG_EX_DEFAULT(WHBLogPrintf, "##INFO ## ", "", FMT, ##ARGS) #define DEBUG_FUNCTION_LINE_ERR_LAMBDA(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, WHBLogPrintf, "##ERROR## ", "", FMT, ##ARGS); @@ -54,6 +55,7 @@ extern "C" { #define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##ERROR## ", "\n", FMT, ##ARGS) #define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##WARN ## ", "\n", FMT, ##ARGS) +#define DEBUG_FUNCTION_LINE_INFO(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##INFO ## ", "\n", FMT, ##ARGS) #define DEBUG_FUNCTION_LINE_ERR_LAMBDA(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, OSReport, "##ERROR## ", "\n", FMT, ##ARGS);