Add support for mirroring the TV/DRC

This commit is contained in:
Maschell 2024-03-03 18:04:14 +01:00
parent 709868e825
commit 0221a05d96
7 changed files with 117 additions and 30 deletions

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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<SwipSwapAudioMode>(newValue);
} else if (std::string_view(SCREEN_MODE_CONFIG_STRING) == item->identifier) {
gCurScreenMode = static_cast<SwipSwapScreenMode>(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));

View File

@ -7,16 +7,18 @@
#include <wups/storage.h>
#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"

View File

@ -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);