mirror of
https://github.com/wiiu-env/region_free_plugin.git
synced 2024-11-21 10:59:16 +01:00
Reimplement/refactor everything
This commit is contained in:
parent
a7b9626818
commit
a6619ab33d
@ -2,5 +2,6 @@ FROM ghcr.io/wiiu-env/devkitppc:20231112
|
||||
|
||||
COPY --from=ghcr.io/wiiu-env/wiiupluginsystem:0.8.0-dev-20231221-ca17105 /artifacts $DEVKITPRO
|
||||
COPY --from=ghcr.io/wiiu-env/libmappedmemory:20230621 /artifacts $DEVKITPRO
|
||||
COPY --from=ghcr.io/wiiu-env/libnotifications:20230621 /artifacts $DEVKITPRO
|
||||
|
||||
WORKDIR project
|
||||
|
2
Makefile
2
Makefile
@ -50,7 +50,7 @@ CXXFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
||||
CFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
||||
endif
|
||||
|
||||
LIBS := -lwups -lwut -lmappedmemory
|
||||
LIBS := -lwups -lwut -lnotifications -lmappedmemory
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level
|
||||
|
68
src/function_patches.cpp
Normal file
68
src/function_patches.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include "utils/SettingsUtils.h"
|
||||
#include "utils/logger.h"
|
||||
#include <coreinit/debug.h>
|
||||
#include <coreinit/userconfig.h>
|
||||
#include <nn/acp/title.h>
|
||||
#include <string_view>
|
||||
#include <sysapp/switch.h>
|
||||
#include <sysapp/title.h>
|
||||
#include <wups/function_patching.h>
|
||||
|
||||
DECL_FUNCTION(int32_t, ACPGetTitleMetaXmlByDevice, uint64_t titleid, ACPMetaXml *metaxml, uint32_t device) {
|
||||
int result = real_ACPGetTitleMetaXmlByDevice(titleid, metaxml, device);
|
||||
if (metaxml != nullptr) {
|
||||
metaxml->region = 0xFFFFFFFF;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DECL_FUNCTION(int32_t, ACPGetLaunchMetaXml, ACPMetaXml *metaxml) {
|
||||
int result = real_ACPGetLaunchMetaXml(metaxml);
|
||||
if (metaxml != nullptr) {
|
||||
metaxml->region = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DECL_FUNCTION(int, UCReadSysConfig, int IOHandle, int count, UCSysConfig *settings) {
|
||||
int result = real_UCReadSysConfig(IOHandle, count, settings);
|
||||
auto upid = OSGetUPID();
|
||||
|
||||
if (!gRegionFreeValuesSetupDone || result != 0 || (upid != SYSAPP_PFID_WII_U_MENU && upid != SYSAPP_PFID_DOWNLOAD_GAME && upid != SYSAPP_PFID_EMANUAL)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (std::string_view("cafe.language") == settings->name) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("UCReadSysConfig: cafe.language found!");
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("UCReadSysConfig: forcing language...");
|
||||
DEBUG_FUNCTION_LINE("UCReadSysConfig: original lang %d, new %d", *((int *) settings->data), gCurrentLanguage);
|
||||
*((int *) settings->data) = gCurrentLanguage;
|
||||
} else if (std::string_view("cafe.cntry_reg") == settings->name) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("UCReadSysConfig: cafe.cntry_reg found!");
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("UCReadSysConfig: forcing cntry_reg...");
|
||||
DEBUG_FUNCTION_LINE("UCReadSysConfig: original cntry_reg %d, new %d", *((int *) settings->data), gCurrentCountry);
|
||||
*((int *) settings->data) = gCurrentCountry;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DECL_FUNCTION(int, MCP_GetSysProdSettings, int IOHandle, MCPSysProdSettings *settings) {
|
||||
int result = real_MCP_GetSysProdSettings(IOHandle, settings);
|
||||
auto upid = OSGetUPID();
|
||||
if (!gRegionFreeValuesSetupDone || result != 0 || (upid != SYSAPP_PFID_WII_U_MENU && upid != SYSAPP_PFID_DOWNLOAD_GAME && upid != SYSAPP_PFID_EMANUAL)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("MCP_GetSysProdSettings: forcing platform region...");
|
||||
DEBUG_FUNCTION_LINE("MCP_GetSysProdSettings: original region %d, new %d...", settings->product_area, gCurrentProductArea);
|
||||
settings->product_area = gCurrentProductArea;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
WUPS_MUST_REPLACE(ACPGetTitleMetaXmlByDevice, WUPS_LOADER_LIBRARY_NN_ACP, ACPGetTitleMetaXmlByDevice);
|
||||
WUPS_MUST_REPLACE(ACPGetLaunchMetaXml, WUPS_LOADER_LIBRARY_NN_ACP, ACPGetLaunchMetaXml);
|
||||
WUPS_MUST_REPLACE_FOR_PROCESS(MCP_GetSysProdSettings, WUPS_LOADER_LIBRARY_COREINIT, MCP_GetSysProdSettings, WUPS_FP_TARGET_PROCESS_ALL);
|
||||
WUPS_MUST_REPLACE_FOR_PROCESS(UCReadSysConfig, WUPS_LOADER_LIBRARY_COREINIT, UCReadSysConfig, WUPS_FP_TARGET_PROCESS_ALL);
|
7
src/function_patches.h
Normal file
7
src/function_patches.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <coreinit/mcp.h>
|
||||
#include <coreinit/userconfig.h>
|
||||
|
||||
extern "C" int (*real_UCReadSysConfig)(int IOHandle, int count, UCSysConfig *settings) __attribute__((section(".data")));
|
||||
extern "C" int (*real_MCP_GetSysProdSettings)(int IOHandle, MCPSysProdSettings *settings) __attribute__((section(".data")));
|
@ -1,21 +1,22 @@
|
||||
#include "globals.h"
|
||||
|
||||
std::optional<MCPRegion> gRealRegionOpt = {};
|
||||
std::optional<int32_t> gRealCountryOpt = {};
|
||||
std::optional<Languages> gRealLanguageOpt = {};
|
||||
|
||||
bool gRegionFreeValuesSetupDone = false;
|
||||
|
||||
bool gPreferSystemSettings = DEFAULT_PREFER_SYSTEM_SETTINGS;
|
||||
bool gSkipOwnRegion = DEFAULT_SKIP_OWN_REGION;
|
||||
bool gAutoDetection = DEFAULT_AUTO_DETECTION_VALUE;
|
||||
|
||||
int gForceSettingsEnabled = 0;
|
||||
Lanuages gDefaultLanguage = LANG_ENGLISH;
|
||||
int32_t gDefaultCountry = 78;
|
||||
MCPRegion gDefaultProductArea = MCP_REGION_EUROPE;
|
||||
Languages gCurrentLanguage = LANG_ENGLISH;
|
||||
int32_t gCurrentCountry = 0;
|
||||
MCPRegion gCurrentProductArea = MCP_REGION_USA;
|
||||
|
||||
Lanuages gCurrentLanguage = gDefaultLanguage;
|
||||
int32_t gCurrentCountry = gDefaultCountry;
|
||||
MCPRegion gCurrentProductArea = gDefaultProductArea;
|
||||
|
||||
Lanuages gDefaultLangForEUR = DEFAULT_LANG_FOR_EUR;
|
||||
Languages gDefaultLangForEUR = DEFAULT_LANG_FOR_EUR;
|
||||
int32_t gDefaultCountryForEUR = DEFAULT_COUNTRY_FOR_EUR;
|
||||
Lanuages gDefaultLangForUSA = DEFAULT_LANG_FOR_USA;
|
||||
Languages gDefaultLangForUSA = DEFAULT_LANG_FOR_USA;
|
||||
int32_t gDefaultCountryForUSA = DEFAULT_COUNTRY_FOR_USA;
|
||||
Lanuages gDefaultLangForJPN = DEFAULT_LANG_FOR_JPN;
|
||||
Languages gDefaultLangForJPN = DEFAULT_LANG_FOR_JPN;
|
||||
int32_t gDefaultCountryForJPN = DEFAULT_COUNTRY_FOR_JPN;
|
@ -2,13 +2,12 @@
|
||||
|
||||
#include "version.h"
|
||||
#include <coreinit/mcp.h>
|
||||
#include <optional>
|
||||
|
||||
#define VERSION "v0.2.3"
|
||||
#define VERSION "v0.2.4"
|
||||
#define VERSION_FULL VERSION VERSION_EXTRA
|
||||
|
||||
extern int gForceSettingsEnabled;
|
||||
|
||||
enum Lanuages {
|
||||
enum Languages {
|
||||
LANG_JAPANESE = 0,
|
||||
LANG_ENGLISH = 1,
|
||||
LANG_FRANCAIS = 2,
|
||||
@ -20,6 +19,12 @@ enum Lanuages {
|
||||
LANG_RUSSKI = 10,
|
||||
};
|
||||
|
||||
extern std::optional<MCPRegion> gRealRegionOpt;
|
||||
extern std::optional<int32_t> gRealCountryOpt;
|
||||
extern std::optional<Languages> gRealLanguageOpt;
|
||||
|
||||
extern bool gRegionFreeValuesSetupDone;
|
||||
|
||||
#define DEFAULT_AUTO_DETECTION_VALUE true
|
||||
extern bool gAutoDetection;
|
||||
|
||||
@ -29,11 +34,7 @@ extern bool gPreferSystemSettings;
|
||||
#define DEFAULT_SKIP_OWN_REGION true
|
||||
extern bool gSkipOwnRegion;
|
||||
|
||||
extern Lanuages gDefaultLanguage;
|
||||
extern int32_t gDefaultCountry;
|
||||
extern MCPRegion gDefaultProductArea;
|
||||
|
||||
extern Lanuages gCurrentLanguage;
|
||||
extern Languages gCurrentLanguage;
|
||||
extern int32_t gCurrentCountry;
|
||||
extern MCPRegion gCurrentProductArea;
|
||||
|
||||
@ -46,11 +47,11 @@ extern MCPRegion gCurrentProductArea;
|
||||
#define DEFAULT_LANG_FOR_JPN LANG_JAPANESE
|
||||
#define DEFAULT_COUNTRY_FOR_JPN 1
|
||||
|
||||
extern Lanuages gDefaultLangForEUR;
|
||||
extern Languages gDefaultLangForEUR;
|
||||
extern int32_t gDefaultCountryForEUR;
|
||||
|
||||
extern Lanuages gDefaultLangForUSA;
|
||||
extern Languages gDefaultLangForUSA;
|
||||
extern int32_t gDefaultCountryForUSA;
|
||||
|
||||
extern Lanuages gDefaultLangForJPN;
|
||||
extern Languages gDefaultLangForJPN;
|
||||
extern int32_t gDefaultCountryForJPN;
|
||||
|
655
src/main.cpp
655
src/main.cpp
@ -1,19 +1,12 @@
|
||||
#include "globals.h"
|
||||
#include "utils/ConfigUtils.h"
|
||||
#include "utils/SettingsUtils.h"
|
||||
#include "utils/WUPSConfigUtils.h"
|
||||
#include "utils/logger.h"
|
||||
#include <coreinit/debug.h>
|
||||
#include <coreinit/mcp.h>
|
||||
#include <coreinit/title.h>
|
||||
#include <coreinit/userconfig.h>
|
||||
#include <cstdio>
|
||||
#include <malloc.h>
|
||||
#include <map>
|
||||
#include <nn/acp.h>
|
||||
#include <sysapp/switch.h>
|
||||
#include <sysapp/title.h>
|
||||
#include <nn/acp/client.h>
|
||||
#include <notifications/notifications.h>
|
||||
#include <wups.h>
|
||||
#include <wups/config/WUPSConfigItemBoolean.h>
|
||||
#include <wups/config/WUPSConfigItemMultipleValues.h>
|
||||
|
||||
WUPS_PLUGIN_NAME("Region Free Plugin");
|
||||
WUPS_PLUGIN_DESCRIPTION("Allows the user to load titles from other regions");
|
||||
@ -24,574 +17,156 @@ WUPS_PLUGIN_LICENSE("GPL");
|
||||
WUPS_USE_WUT_DEVOPTAB();
|
||||
WUPS_USE_STORAGE("region_free_plugin");
|
||||
|
||||
bool getRealProductArea(MCPRegion *out);
|
||||
void SetupRegionSpoofing() {
|
||||
ACPInitialize(); // We need to this for getting the region of the current title
|
||||
|
||||
DECL_FUNCTION(int32_t, ACPGetLaunchMetaXml, ACPMetaXml *metaxml) {
|
||||
int result = real_ACPGetLaunchMetaXml(metaxml);
|
||||
if (metaxml != nullptr) {
|
||||
metaxml->region = 0xFFFFFFFF;
|
||||
}
|
||||
// By default, always use the real values
|
||||
gCurrentLanguage = gRealLanguageOpt.value();
|
||||
gCurrentProductArea = gRealRegionOpt.value();
|
||||
gCurrentCountry = gRealCountryOpt.value();
|
||||
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* 1. No do any region/language/country changes for the Wii U Menu
|
||||
* 2. Try to get the region from the xml of the title that is currently running
|
||||
* 2a. If we are able to determine the region of the title, set the current region/language/country to the default region/language/country of that region
|
||||
* 2b. If we are NOT able to determine the region of the title, make sure to force open the config menu
|
||||
* If reading the XML of the current title fails, make sure to force open the config menu
|
||||
* 3. If the current region is equal to the real region
|
||||
* - make sure to reset the country to the real country
|
||||
* - set the language back to the system language if requested (see "Prefer system settings for in region title"-setting)
|
||||
* 4. Try to read the region/language for the currently running title from the storage.
|
||||
* - If the settings for these settings do no exists, create an entry with the current values (unless the menu is forced opened)
|
||||
* - The values from the storage always have the highest priority
|
||||
* - Currently the country is NOT loaded from the storage (is not stored to storage).
|
||||
* 5. Open the region free config menu if the auto detection is enabled, or we failed to determine the region of the currently running title.
|
||||
*/
|
||||
|
||||
DECL_FUNCTION(int, UCReadSysConfig, int IOHandle, int count, struct UCSysConfig *settings) {
|
||||
int result = real_UCReadSysConfig(IOHandle, count, settings);
|
||||
auto upid = OSGetUPID();
|
||||
if (upid != SYSAPP_PFID_WII_U_MENU && upid != SYSAPP_PFID_DOWNLOAD_GAME && upid != SYSAPP_PFID_EMANUAL) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (gForceSettingsEnabled) {
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (std::string_view("cafe.language") == settings->name) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("UCReadSysConfig: cafe.language found!");
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("UCReadSysConfig: forcing language...");
|
||||
DEBUG_FUNCTION_LINE("UCReadSysConfig: original lang %d, new %d", *((int *) settings->data), gCurrentLanguage);
|
||||
*((int *) settings->data) = gCurrentLanguage;
|
||||
}
|
||||
if (std::string_view("cafe.cntry_reg") == settings->name) {
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("UCReadSysConfig: cafe.cntry_reg found!");
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("UCReadSysConfig: forcing cntry_reg...");
|
||||
DEBUG_FUNCTION_LINE("UCReadSysConfig: original cntry_reg %d, new %d", *((int *) settings->data), gCurrentCountry);
|
||||
*((int *) settings->data) = gCurrentCountry;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define CAT_GENERAL_ROOT "root"
|
||||
#define CAT_GENERAL_SETTINGS "general_settings"
|
||||
#define CAT_TITLE_SETTINGS "title_settings"
|
||||
|
||||
#define VAL_LANGUAGE "language"
|
||||
#define VAL_COUNTRY "cntry_reg"
|
||||
#define VAL_PRODUCT_AREA "product_area"
|
||||
|
||||
#define VAL_SKIP_OWN_REGION "skip_own_region"
|
||||
#define VAL_PREFER_SYSTEM_SETTINGS "prefer_system_settings"
|
||||
#define VAL_AUTO_DETECTION "auto_detection"
|
||||
#define VAL_DEFAULT_LANG_EUR "default_lang_eur"
|
||||
#define VAL_DEFAULT_LANG_USA "default_lang_usa"
|
||||
#define VAL_DEFAULT_LANG_JPN "default_lang_jpn"
|
||||
|
||||
#define VAL_DEFAULT_COUNTRY_EUR "default_cntry_reg_eur"
|
||||
#define VAL_DEFAULT_COUNTRY_USA "default_cntry_reg_usa"
|
||||
#define VAL_DEFAULT_COUNTRY_JPN "default_cntry_reg_jpn"
|
||||
|
||||
DECL_FUNCTION(int32_t, ACPGetTitleMetaXmlByDevice, uint32_t titleid_upper, uint32_t titleid_lower, ACPMetaXml *metaxml, uint32_t device) {
|
||||
int result = real_ACPGetTitleMetaXmlByDevice(titleid_upper, titleid_lower, metaxml, device);
|
||||
if (metaxml != nullptr) {
|
||||
metaxml->region = 0xFFFFFFFF;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void bootStuff() {
|
||||
MCPRegion real_product_area;
|
||||
auto real_product_area_valid = getRealProductArea(&real_product_area);
|
||||
if (real_product_area_valid) {
|
||||
if (real_product_area == MCP_REGION_EUROPE) {
|
||||
gDefaultProductArea = MCP_REGION_EUROPE;
|
||||
gDefaultLanguage = gDefaultLangForEUR;
|
||||
gDefaultCountry = gDefaultCountryForEUR;
|
||||
} else if (real_product_area == MCP_REGION_JAPAN) {
|
||||
gDefaultProductArea = MCP_REGION_JAPAN;
|
||||
gDefaultLanguage = gDefaultLangForJPN;
|
||||
gDefaultCountry = gDefaultCountryForJPN;
|
||||
}
|
||||
if (real_product_area == MCP_REGION_USA) {
|
||||
gDefaultProductArea = MCP_REGION_USA;
|
||||
gDefaultLanguage = gDefaultLangForUSA;
|
||||
gDefaultCountry = gDefaultCountryForUSA;
|
||||
}
|
||||
}
|
||||
|
||||
bool forceConfigMenu = false;
|
||||
auto *acpMetaXml = (ACPMetaXml *) memalign(0x40, sizeof(ACPMetaXml));
|
||||
uint32_t regionFromXML = 0;
|
||||
if (acpMetaXml) {
|
||||
memset(acpMetaXml, 0, sizeof(ACPMetaXml));
|
||||
ACPInitialize();
|
||||
auto res = ACPGetTitleMetaXml(OSGetTitleID(), acpMetaXml);
|
||||
if (res >= 0) {
|
||||
regionFromXML = acpMetaXml->region;
|
||||
if (real_product_area_valid && (regionFromXML & real_product_area) == real_product_area) {
|
||||
gCurrentProductArea = real_product_area;
|
||||
} else {
|
||||
auto curTitleId = OSGetTitleID();
|
||||
if (curTitleId == 0x0005001010040000L || regionFromXML == 1) {
|
||||
DEBUG_FUNCTION_LINE("Set default to JAPAN");
|
||||
gDefaultProductArea = MCP_REGION_JAPAN;
|
||||
gDefaultLanguage = gDefaultLangForJPN;
|
||||
gDefaultCountry = gDefaultCountryForJPN;
|
||||
} else if (curTitleId == 0x0005001010040100L || regionFromXML == 2) {
|
||||
DEBUG_FUNCTION_LINE("Set default to USA");
|
||||
gDefaultProductArea = MCP_REGION_USA;
|
||||
gDefaultLanguage = gDefaultLangForUSA;
|
||||
gDefaultCountry = gDefaultCountryForUSA;
|
||||
} else if (curTitleId == 0x0005001010040200L || curTitleId == 0x0005001001004E200L || regionFromXML == 4) {
|
||||
DEBUG_FUNCTION_LINE("Set default to EUR");
|
||||
gDefaultProductArea = MCP_REGION_EUROPE;
|
||||
gDefaultLanguage = gDefaultLangForEUR;
|
||||
gDefaultCountry = gDefaultCountryForEUR;
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_ERR("Unknown area %08X, force menu", acpMetaXml->region);
|
||||
forceConfigMenu = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_ERR("ACPGetTitleMetaXml failed");
|
||||
forceConfigMenu = true;
|
||||
}
|
||||
ACPFinalize();
|
||||
free(acpMetaXml);
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to allocate acpMetaXml");
|
||||
forceConfigMenu = true;
|
||||
}
|
||||
|
||||
// Get region and lang from console and set these as default.
|
||||
gCurrentLanguage = gDefaultLanguage;
|
||||
gCurrentCountry = gDefaultCountry;
|
||||
gCurrentProductArea = gDefaultProductArea;
|
||||
|
||||
if (gPreferSystemSettings && real_product_area_valid) {
|
||||
if ((regionFromXML & real_product_area) == real_product_area) {
|
||||
gCurrentProductArea = real_product_area;
|
||||
|
||||
auto ucHandle = UCOpen();
|
||||
if (ucHandle >= 0) {
|
||||
UCSysConfig sysConfig;
|
||||
memset((void *) &sysConfig, 0, sizeof(sysConfig));
|
||||
uint32_t data = 0xFFFFFFFF;
|
||||
sysConfig.dataType = UC_DATATYPE_UNSIGNED_INT;
|
||||
sysConfig.dataSize = 4;
|
||||
sysConfig.data = &data;
|
||||
strncpy(sysConfig.name, "cafe.language", 64);
|
||||
int ucRes = real_UCReadSysConfig(ucHandle, 1, &sysConfig);
|
||||
|
||||
if (ucRes >= 0) {
|
||||
DEBUG_FUNCTION_LINE("Force default language to system language for own region");
|
||||
gCurrentLanguage = static_cast<Lanuages>(*(uint32_t *) sysConfig.data);
|
||||
gDefaultLanguage = static_cast<Lanuages>(*(uint32_t *) sysConfig.data);
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_ERR("UCReadSysConfig failed");
|
||||
}
|
||||
|
||||
memset((void *) &sysConfig, 0, sizeof(sysConfig));
|
||||
data = 0xFFFFFFFF;
|
||||
sysConfig.dataType = UC_DATATYPE_UNSIGNED_INT;
|
||||
sysConfig.dataSize = 4;
|
||||
sysConfig.data = &data;
|
||||
strncpy(sysConfig.name, "cafe.cntry_reg", 64);
|
||||
ucRes = real_UCReadSysConfig(ucHandle, 1, &sysConfig);
|
||||
|
||||
if (ucRes >= 0) {
|
||||
DEBUG_FUNCTION_LINE("Force default country to system country for own region");
|
||||
gCurrentCountry = (int32_t) * (uint32_t *) sysConfig.data;
|
||||
gDefaultCountry = (int32_t) * (uint32_t *) sysConfig.data;
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_ERR("UCReadSysConfig failed");
|
||||
}
|
||||
UCClose(ucHandle);
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_ERR("UCOpen failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
WUPSStorageError storageError;
|
||||
auto rootStorage = WUPSStorageAPI::GetSubItem(CAT_GENERAL_ROOT, storageError);
|
||||
if (!rootStorage) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to read %s subitem", CAT_GENERAL_ROOT);
|
||||
return;
|
||||
}
|
||||
auto titleSettings = rootStorage->GetOrCreateSubItem(CAT_TITLE_SETTINGS, storageError);
|
||||
if (!titleSettings) {
|
||||
DEBUG_FUNCTION_LINE_ERR("WUPS_CreateSubItem %s failed", CAT_TITLE_SETTINGS);
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[18];
|
||||
snprintf(buffer, 17, "%016llX", OSGetTitleID());
|
||||
|
||||
auto curTitle = titleSettings->GetOrCreateSubItem(buffer, storageError);
|
||||
|
||||
if (!curTitle) {
|
||||
DEBUG_FUNCTION_LINE_ERR("WUPS_CreateSubItem %s failed", buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
storageError = curTitle->GetOrStoreDefault(VAL_LANGUAGE, gCurrentLanguage, gCurrentLanguage);
|
||||
if (storageError != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or store current Language");
|
||||
}
|
||||
storageError = curTitle->GetOrStoreDefault(VAL_PRODUCT_AREA, gCurrentProductArea, gCurrentProductArea);
|
||||
if (storageError != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or store current Language");
|
||||
}
|
||||
|
||||
bool isWiiUMenu = false;
|
||||
bool forceOpenConfigMenu = false;
|
||||
bool isWiiUMenu = false;
|
||||
if (OSGetTitleID() == 0x0005001010040000L || // Wii U Menu JPN
|
||||
OSGetTitleID() == 0x0005001010040100L || // Wii U Menu USA
|
||||
OSGetTitleID() == 0x0005001010040200L) { // Wii U Menu EUR
|
||||
isWiiUMenu = true;
|
||||
}
|
||||
|
||||
bool showMenu = !gAutoDetection;
|
||||
if (!isWiiUMenu) {
|
||||
// Set current values based on title xml
|
||||
auto regionForCurrentTitleOpt = getRegionForTitle(OSGetTitleID());
|
||||
if (regionForCurrentTitleOpt) {
|
||||
auto region_from_xml = regionForCurrentTitleOpt.value();
|
||||
if ((region_from_xml & gCurrentProductArea) == gCurrentProductArea) {
|
||||
// get current product area
|
||||
} else if (region_from_xml == 1) {
|
||||
gCurrentProductArea = MCP_REGION_JAPAN;
|
||||
gCurrentLanguage = gDefaultLangForJPN;
|
||||
gCurrentCountry = gDefaultCountryForJPN;
|
||||
} else if (region_from_xml == 2) {
|
||||
gCurrentProductArea = MCP_REGION_USA;
|
||||
gCurrentLanguage = gDefaultLangForUSA;
|
||||
gCurrentCountry = gDefaultCountryForUSA;
|
||||
} else if (region_from_xml == 4) {
|
||||
gCurrentProductArea = MCP_REGION_EUROPE;
|
||||
gCurrentLanguage = gDefaultLangForEUR;
|
||||
gCurrentCountry = gDefaultCountryForEUR;
|
||||
} else {
|
||||
// Unknown region in xml, force open the config menu
|
||||
forceOpenConfigMenu = true;
|
||||
}
|
||||
} else {
|
||||
// Failed to get region for current tile, force open the config menu
|
||||
forceOpenConfigMenu = true;
|
||||
}
|
||||
|
||||
if (real_product_area_valid && (regionFromXML & real_product_area) == real_product_area) {
|
||||
if (gSkipOwnRegion && !forceConfigMenu) {
|
||||
// If the launched title is for real region, force the country (and maybe language) to be the real one
|
||||
if (gRealRegionOpt.value() == gCurrentProductArea) {
|
||||
// Check if we want to keep the system language for in-region titles.
|
||||
if (gPreferSystemSettings) {
|
||||
gCurrentLanguage = gRealLanguageOpt.value();
|
||||
}
|
||||
// For now always use the real country
|
||||
gCurrentCountry = gRealCountryOpt.value();
|
||||
}
|
||||
|
||||
// Read per-title settings. Give current lang/region as default values.
|
||||
// If we don't have values yet for this title, we only create them if we could get the region for the current title
|
||||
bool allowDefaultValues = !forceOpenConfigMenu;
|
||||
auto titleRegionInfoOpt = getTitleRegionInfo(OSGetTitleID(), gCurrentLanguage, gCurrentProductArea, allowDefaultValues);
|
||||
if (titleRegionInfoOpt) {
|
||||
gCurrentProductArea = titleRegionInfoOpt->product_area;
|
||||
gCurrentLanguage = titleRegionInfoOpt->language;
|
||||
}
|
||||
}
|
||||
|
||||
// show menu if we don't use auto-detection
|
||||
bool showMenu = !gAutoDetection;
|
||||
if (gCurrentProductArea == gRealRegionOpt.value()) {
|
||||
if (gSkipOwnRegion && !forceOpenConfigMenu) {
|
||||
// If the want to skip checks for own region, and we were able
|
||||
// to tell the region of the current title don't show the menu.
|
||||
showMenu = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// this overrides the current settings
|
||||
if (forceConfigMenu || (!isWiiUMenu && showMenu)) {
|
||||
if (forceOpenConfigMenu || (!isWiiUMenu && showMenu)) {
|
||||
ConfigUtils::openConfigMenu();
|
||||
// Save settings to storage
|
||||
curTitle->Store(VAL_LANGUAGE, gCurrentLanguage);
|
||||
curTitle->Store(VAL_PRODUCT_AREA, gCurrentProductArea);
|
||||
// Save (updated) title settings to the storage
|
||||
if (!saveTitleRegionInfo({OSGetTitleID(), gCurrentLanguage, gCurrentProductArea})) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to save current title region info to storage");
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_FUNCTION_LINE("Language will be force to %d", gCurrentLanguage);
|
||||
DEBUG_FUNCTION_LINE("Country will be force to %d", gDefaultCountry);
|
||||
DEBUG_FUNCTION_LINE("Language will be forced to %d", gCurrentLanguage);
|
||||
DEBUG_FUNCTION_LINE("Country will be forced to %d", gCurrentCountry);
|
||||
DEBUG_FUNCTION_LINE("Product Area will be forced to %d", gCurrentProductArea);
|
||||
}
|
||||
|
||||
std::optional<WUPSStorageSubItem> rootSettingsStorage = {};
|
||||
std::optional<WUPSStorageSubItem> generalSettingsStorage = {};
|
||||
static bool disableRegionFreePlugin = false;
|
||||
|
||||
ON_APPLICATION_START() {
|
||||
initLogging();
|
||||
|
||||
WUPSStorageError storageError;
|
||||
rootSettingsStorage = WUPSStorageAPI::GetOrCreateSubItem(CAT_GENERAL_ROOT, storageError);
|
||||
if (!rootSettingsStorage) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or create %s subitem", CAT_GENERAL_ROOT);
|
||||
}
|
||||
|
||||
generalSettingsStorage = rootSettingsStorage->GetOrCreateSubItem(CAT_GENERAL_SETTINGS, storageError);
|
||||
if (!generalSettingsStorage) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or create %s subitem", CAT_GENERAL_SETTINGS);
|
||||
if (disableRegionFreePlugin) {
|
||||
gRegionFreeValuesSetupDone = false;
|
||||
} else {
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_AUTO_DETECTION, gAutoDetection, DEFAULT_AUTO_DETECTION_VALUE)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_PREFER_SYSTEM_SETTINGS, gPreferSystemSettings, DEFAULT_PREFER_SYSTEM_SETTINGS)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_SKIP_OWN_REGION, gSkipOwnRegion, DEFAULT_SKIP_OWN_REGION)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_DEFAULT_LANG_EUR, gDefaultLangForEUR, DEFAULT_LANG_FOR_EUR)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_DEFAULT_COUNTRY_EUR, gDefaultCountryForEUR, DEFAULT_COUNTRY_FOR_EUR)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_DEFAULT_LANG_USA, gDefaultLangForUSA, DEFAULT_LANG_FOR_USA)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_DEFAULT_COUNTRY_USA, gDefaultCountryForUSA, DEFAULT_COUNTRY_FOR_USA)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_DEFAULT_LANG_JPN, gDefaultLangForJPN, DEFAULT_LANG_FOR_JPN)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_DEFAULT_COUNTRY_JPN, gDefaultCountryForJPN, DEFAULT_COUNTRY_FOR_JPN)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
SetupRegionSpoofing();
|
||||
gRegionFreeValuesSetupDone = true;
|
||||
}
|
||||
|
||||
gForceSettingsEnabled = 1;
|
||||
if (OSGetTitleID() == 0x0005001010040000L || // Wii U Menu JPN
|
||||
OSGetTitleID() == 0x0005001010040100L || // Wii U Menu USA
|
||||
OSGetTitleID() == 0x0005001010040200L) { // Wii U Menu EUR
|
||||
gForceSettingsEnabled = 0;
|
||||
}
|
||||
|
||||
bootStuff();
|
||||
|
||||
WUPSStorageAPI::SaveStorage();
|
||||
}
|
||||
|
||||
void bool_item_changed(ConfigItemBoolean *item, bool newValue) {
|
||||
DEBUG_FUNCTION_LINE("Value changed for %s: %d", item->identifier ? item->identifier : "[UNKNOWN]", newValue);
|
||||
|
||||
if (std::string_view(VAL_DEFAULT_LANG_USA) == item->identifier) {
|
||||
gAutoDetection = newValue;
|
||||
if (generalSettingsStorage) {
|
||||
generalSettingsStorage->Store(VAL_AUTO_DETECTION, gAutoDetection);
|
||||
}
|
||||
} else if (std::string_view(VAL_PREFER_SYSTEM_SETTINGS) == item->identifier) {
|
||||
gPreferSystemSettings = newValue;
|
||||
if (generalSettingsStorage) {
|
||||
generalSettingsStorage->Store(VAL_PREFER_SYSTEM_SETTINGS, gPreferSystemSettings);
|
||||
}
|
||||
} else if (std::string_view(VAL_SKIP_OWN_REGION) == item->identifier) {
|
||||
gPreferSystemSettings = newValue;
|
||||
if (generalSettingsStorage) {
|
||||
generalSettingsStorage->Store(VAL_SKIP_OWN_REGION, gSkipOwnRegion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void default_lang_changed(ConfigItemMultipleValues *item, uint32_t newValue) {
|
||||
DEBUG_FUNCTION_LINE("New value in %s changed: %d", item->configId, newValue);
|
||||
|
||||
if (std::string_view(VAL_DEFAULT_LANG_EUR) == item->identifier) {
|
||||
DEBUG_FUNCTION_LINE("Updated default eur lang");
|
||||
gDefaultLangForEUR = (Lanuages) newValue;
|
||||
} else if (std::string_view(VAL_DEFAULT_LANG_USA) == item->identifier) {
|
||||
DEBUG_FUNCTION_LINE("Updated default usa lang");
|
||||
gDefaultLangForUSA = (Lanuages) newValue;
|
||||
} else if (std::string_view(VAL_DEFAULT_LANG_JPN) == item->identifier) {
|
||||
DEBUG_FUNCTION_LINE("Updated default jpn lang");
|
||||
gDefaultLangForJPN = (Lanuages) newValue;
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_WARN("Unexpected identifier for default_lang_changed");
|
||||
return;
|
||||
}
|
||||
if (generalSettingsStorage) {
|
||||
generalSettingsStorage->Store(item->identifier, (int32_t) newValue);
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to store into general settings: sub-item was nullopt");
|
||||
}
|
||||
}
|
||||
|
||||
static WUPSConfigAPICallbackStatus ConfigMenuOpenedCallback(WUPSConfigCategoryHandle rootHandle) {
|
||||
try {
|
||||
WUPSConfigCategory root = WUPSConfigCategory(rootHandle);
|
||||
|
||||
root.add(WUPSConfigItemBoolean::Create(VAL_DEFAULT_LANG_USA, "Auto detect region/language",
|
||||
DEFAULT_AUTO_DETECTION_VALUE, gAutoDetection,
|
||||
&bool_item_changed));
|
||||
root.add(WUPSConfigItemBoolean::Create(VAL_SKIP_OWN_REGION, "Force auto detection for in-region titles",
|
||||
DEFAULT_SKIP_OWN_REGION, gSkipOwnRegion,
|
||||
&bool_item_changed));
|
||||
root.add(WUPSConfigItemBoolean::Create(VAL_PREFER_SYSTEM_SETTINGS, "Prefer system settings for in-region titles",
|
||||
DEFAULT_PREFER_SYSTEM_SETTINGS, gPreferSystemSettings,
|
||||
&bool_item_changed));
|
||||
|
||||
constexpr WUPSConfigItemMultipleValues::ValuePair eur_lang_map[] = {
|
||||
{LANG_ENGLISH, "English"},
|
||||
{LANG_FRANCAIS, "Francais"},
|
||||
{LANG_DEUTSCH, "Deutsch"},
|
||||
{LANG_ITALIANO, "Italiano"},
|
||||
{LANG_ESPANOL, "Espanol"},
|
||||
{LANG_NEDERLANDS, "Nederlands"},
|
||||
{LANG_PORTUGUES, "Portugues"},
|
||||
{LANG_RUSSKI, "Russki"},
|
||||
};
|
||||
|
||||
root.add(WUPSConfigItemMultipleValues::CreateFromValue(VAL_DEFAULT_LANG_EUR, "Default language for EUR",
|
||||
DEFAULT_LANG_FOR_EUR, gDefaultLangForEUR,
|
||||
eur_lang_map,
|
||||
default_lang_changed));
|
||||
|
||||
constexpr WUPSConfigItemMultipleValues::ValuePair usa_lang_map[] = {
|
||||
{LANG_ENGLISH, "English"},
|
||||
{LANG_FRANCAIS, "Francais"},
|
||||
{LANG_ESPANOL, "Espanol"},
|
||||
{LANG_PORTUGUES, "Portugues"}};
|
||||
|
||||
root.add(WUPSConfigItemMultipleValues::CreateFromValue(VAL_DEFAULT_LANG_USA, "Default language for USA",
|
||||
DEFAULT_LANG_FOR_USA, gDefaultLangForUSA,
|
||||
usa_lang_map,
|
||||
default_lang_changed));
|
||||
|
||||
} catch (std::exception &e) {
|
||||
OSReport("Exception T_T : %s\n", e.what());
|
||||
return WUPSCONFIG_API_CALLBACK_RESULT_ERROR;
|
||||
}
|
||||
return WUPSCONFIG_API_CALLBACK_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static void ConfigMenuClosedCallback() {
|
||||
// Save all changes
|
||||
WUPSStorageAPI::SaveStorage();
|
||||
}
|
||||
|
||||
INITIALIZE_PLUGIN() {
|
||||
initLogging();
|
||||
|
||||
WUPSConfigAPIOptionsV1 configOptions = {.name = "Region Free Plugin"};
|
||||
if (WUPSConfigAPI_Init(configOptions, ConfigMenuOpenedCallback, ConfigMenuClosedCallback) != WUPSCONFIG_API_RESULT_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to init config api");
|
||||
if (NotificationModule_InitLibrary() != NOTIFICATION_MODULE_RESULT_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("NotificationModule_InitLibrary failed");
|
||||
} else {
|
||||
NotificationModule_SetDefaultValue(NOTIFICATION_MODULE_NOTIFICATION_TYPE_ERROR, NOTIFICATION_MODULE_DEFAULT_OPTION_DURATION_BEFORE_FADE_OUT, 10.0f);
|
||||
}
|
||||
|
||||
gRegionFreeValuesSetupDone = false;
|
||||
|
||||
gRealRegionOpt = getRealRegion();
|
||||
gRealCountryOpt = getRealCountry();
|
||||
gRealLanguageOpt = getRealLanguage();
|
||||
|
||||
if (!gRealRegionOpt.has_value() || !gRealCountryOpt.has_value() || !gRealLanguageOpt.has_value()) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get the real region, country or language. Disabling the region free plugin");
|
||||
disableRegionFreePlugin = true;
|
||||
NotificationModuleStatus err;
|
||||
if ((err = NotificationModule_AddErrorNotification("Failed to init Region Free Plugin. The plugin will be disabled until next boot")) != NOTIFICATION_MODULE_RESULT_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to add error notification: %s", NotificationModule_GetStatusStr(err));
|
||||
}
|
||||
}
|
||||
|
||||
InitConfigAndStorage();
|
||||
|
||||
deinitLogging();
|
||||
}
|
||||
|
||||
DECL_FUNCTION(int, MCP_GetSysProdSettings, int IOHandle, struct MCPSysProdSettings *settings) {
|
||||
int result = real_MCP_GetSysProdSettings(IOHandle, settings);
|
||||
|
||||
auto upid = OSGetUPID();
|
||||
if (upid != SYSAPP_PFID_WII_U_MENU && upid != SYSAPP_PFID_DOWNLOAD_GAME && upid != SYSAPP_PFID_EMANUAL) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (gForceSettingsEnabled) {
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("MCP_GetSysProdSettings: forcing platform region...");
|
||||
DEBUG_FUNCTION_LINE("MCP_GetSysProdSettings: original region %d, new %d...", settings->product_area, gCurrentProductArea);
|
||||
settings->product_area = gCurrentProductArea;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static const uint64_t
|
||||
sSysAppTitleId[][3] =
|
||||
{
|
||||
{
|
||||
// Updater
|
||||
0x0005001010040000ull,
|
||||
0x0005001010040100ull,
|
||||
0x0005001010040200ull,
|
||||
},
|
||||
|
||||
{
|
||||
// System Settings
|
||||
0x0005001010047000ull,
|
||||
0x0005001010047100ull,
|
||||
0x0005001010047200ull,
|
||||
},
|
||||
|
||||
{
|
||||
// Parental Controls
|
||||
0x0005001010048000ull,
|
||||
0x0005001010048100ull,
|
||||
0x0005001010048200ull,
|
||||
},
|
||||
|
||||
{
|
||||
// User Settings
|
||||
0x0005001010049000ull,
|
||||
0x0005001010049100ull,
|
||||
0x0005001010049200ull,
|
||||
},
|
||||
|
||||
{
|
||||
// Mii Maker
|
||||
0x000500101004A000ull,
|
||||
0x000500101004A100ull,
|
||||
0x000500101004A200ull,
|
||||
},
|
||||
|
||||
{
|
||||
// Account Settings
|
||||
0x000500101004B000ull,
|
||||
0x000500101004B100ull,
|
||||
0x000500101004B200ull,
|
||||
},
|
||||
|
||||
{
|
||||
// Daily log
|
||||
0x000500101004C000ull,
|
||||
0x000500101004C100ull,
|
||||
0x000500101004C200ull,
|
||||
},
|
||||
|
||||
{
|
||||
// Notifications
|
||||
0x000500101004D000ull,
|
||||
0x000500101004D100ull,
|
||||
0x000500101004D200ull,
|
||||
},
|
||||
|
||||
{
|
||||
// Health and Safety Information
|
||||
0x000500101004E000ull,
|
||||
0x000500101004E100ull,
|
||||
0x000500101004E200ull,
|
||||
},
|
||||
|
||||
{
|
||||
// Electronic Manual
|
||||
0x0005001B10059000ull,
|
||||
0x0005001B10059100ull,
|
||||
0x0005001B10059200ull,
|
||||
},
|
||||
|
||||
{
|
||||
// Wii U Chat
|
||||
0x000500101005A000ull,
|
||||
0x000500101005A100ull,
|
||||
0x000500101005A200ull,
|
||||
},
|
||||
|
||||
{
|
||||
// "Software/Data Transfer"
|
||||
0x0005001010062000ull,
|
||||
0x0005001010062100ull,
|
||||
0x0005001010062200ull,
|
||||
},
|
||||
};
|
||||
|
||||
bool getRealProductArea(MCPRegion *out) {
|
||||
if (out == nullptr) {
|
||||
return false;
|
||||
}
|
||||
auto handle = MCP_Open();
|
||||
if (handle >= 0) {
|
||||
auto data = (struct MCPSysProdSettings *) memalign(0x40, sizeof(struct MCPSysProdSettings));
|
||||
auto res = real_MCP_GetSysProdSettings(handle, data);
|
||||
if (res >= 0) {
|
||||
*out = data->product_area;
|
||||
}
|
||||
MCP_Close(handle);
|
||||
free(data);
|
||||
return res >= 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DECL_FUNCTION(uint64_t, _SYSGetSystemApplicationTitleIdByProdArea, SYSTEM_APP_ID param_1, MCPRegion param_2) {
|
||||
auto upid = OSGetUPID();
|
||||
if (upid != SYSAPP_PFID_WII_U_MENU && upid != SYSAPP_PFID_DOWNLOAD_GAME && upid != SYSAPP_PFID_EMANUAL) {
|
||||
return real__SYSGetSystemApplicationTitleIdByProdArea(param_1, param_2);
|
||||
}
|
||||
MCPRegion cur_product_area;
|
||||
if (!getRealProductArea(&cur_product_area)) {
|
||||
DEBUG_FUNCTION_LINE("Failed to get real region");
|
||||
cur_product_area = param_2;
|
||||
}
|
||||
|
||||
auto regionIdx = 1u;
|
||||
|
||||
if (cur_product_area == MCP_REGION_JAPAN) {
|
||||
regionIdx = 0u;
|
||||
} else if (cur_product_area == MCP_REGION_EUROPE || cur_product_area == 0x08) {
|
||||
regionIdx = 2u;
|
||||
}
|
||||
|
||||
uint64_t res = sSysAppTitleId[param_1][regionIdx];
|
||||
return res;
|
||||
DEINITIALIZE_PLUGIN() {
|
||||
NotificationModule_DeInitLibrary();
|
||||
}
|
||||
|
||||
ON_APPLICATION_ENDS() {
|
||||
gCurrentLanguage = gDefaultLanguage;
|
||||
gCurrentCountry = gDefaultCountry;
|
||||
gCurrentProductArea = gDefaultProductArea;
|
||||
gRegionFreeValuesSetupDone = false;
|
||||
deinitLogging();
|
||||
}
|
||||
|
||||
WUPS_MUST_REPLACE(ACPGetTitleMetaXmlByDevice, WUPS_LOADER_LIBRARY_NN_ACP, ACPGetTitleMetaXmlByDevice);
|
||||
WUPS_MUST_REPLACE(ACPGetLaunchMetaXml, WUPS_LOADER_LIBRARY_NN_ACP, ACPGetLaunchMetaXml);
|
||||
WUPS_MUST_REPLACE_FOR_PROCESS(MCP_GetSysProdSettings, WUPS_LOADER_LIBRARY_COREINIT, MCP_GetSysProdSettings, WUPS_FP_TARGET_PROCESS_ALL);
|
||||
WUPS_MUST_REPLACE_FOR_PROCESS(UCReadSysConfig, WUPS_LOADER_LIBRARY_COREINIT, UCReadSysConfig, WUPS_FP_TARGET_PROCESS_ALL);
|
||||
WUPS_MUST_REPLACE_FOR_PROCESS(_SYSGetSystemApplicationTitleIdByProdArea, WUPS_LOADER_LIBRARY_SYSAPP, _SYSGetSystemApplicationTitleIdByProdArea, WUPS_FP_TARGET_PROCESS_ALL);
|
||||
|
@ -142,7 +142,6 @@ void ConfigUtils::displayMenu() {
|
||||
{MCP_REGION_EUROPE, 2},
|
||||
};
|
||||
|
||||
|
||||
std::map<int32_t, MCPRegion> region_index_to_map{
|
||||
{0, MCP_REGION_JAPAN},
|
||||
{1, MCP_REGION_USA},
|
||||
@ -150,9 +149,9 @@ void ConfigUtils::displayMenu() {
|
||||
};
|
||||
|
||||
auto curSelectedRegion = gCurrentProductArea;
|
||||
DEBUG_FUNCTION_LINE("Current %d", curSelectedRegion);
|
||||
DEBUG_FUNCTION_LINE_VERBOSE("Current %d", curSelectedRegion);
|
||||
|
||||
std::map<Lanuages, const char *> lang_map{
|
||||
std::map<Languages, const char *> lang_map{
|
||||
{LANG_JAPANESE, "Japanese"},
|
||||
{LANG_ENGLISH, "English"},
|
||||
{LANG_FRANCAIS, "Francais"},
|
||||
@ -163,7 +162,7 @@ void ConfigUtils::displayMenu() {
|
||||
{LANG_PORTUGUES, "Portugues"},
|
||||
{LANG_RUSSKI, "Russki"},
|
||||
};
|
||||
std::map<Lanuages, int32_t> lang_map_to_index{
|
||||
std::map<Languages, int32_t> lang_map_to_index{
|
||||
{LANG_JAPANESE, 0},
|
||||
{LANG_ENGLISH, 1},
|
||||
{LANG_FRANCAIS, 2},
|
||||
@ -174,7 +173,7 @@ void ConfigUtils::displayMenu() {
|
||||
{LANG_PORTUGUES, 7},
|
||||
{LANG_RUSSKI, 8},
|
||||
};
|
||||
std::map<int32_t, Lanuages> lang_index_to_map{
|
||||
std::map<int32_t, Languages> lang_index_to_map{
|
||||
{0, LANG_JAPANESE},
|
||||
{1, LANG_ENGLISH},
|
||||
{2, LANG_FRANCAIS},
|
||||
@ -247,8 +246,8 @@ void ConfigUtils::displayMenu() {
|
||||
if (curRegionIndex < 0) {
|
||||
curRegionIndex = 0;
|
||||
}
|
||||
if (curRegionIndex >= region_map.size()) {
|
||||
curRegionIndex = region_map.size() - 1;
|
||||
if (curRegionIndex >= (int32_t) region_map.size()) {
|
||||
curRegionIndex = (int32_t) region_map.size() - 1;
|
||||
}
|
||||
gCurrentProductArea = region_index_to_map[curRegionIndex];
|
||||
curSelectedRegion = gCurrentProductArea;
|
||||
@ -263,8 +262,8 @@ void ConfigUtils::displayMenu() {
|
||||
if (curLangIndex < 0) {
|
||||
curLangIndex = 0;
|
||||
}
|
||||
if (curLangIndex >= lang_map.size()) {
|
||||
curLangIndex = lang_map.size() - 1;
|
||||
if (curLangIndex >= (int32_t) lang_map.size()) {
|
||||
curLangIndex = (int32_t) lang_map.size() - 1;
|
||||
}
|
||||
gCurrentLanguage = lang_index_to_map[curLangIndex];
|
||||
curSelectedLanguage = gCurrentLanguage;
|
||||
@ -293,7 +292,7 @@ void ConfigUtils::displayMenu() {
|
||||
std::string regionText = region_map[curSelectedRegion];
|
||||
if (selectedBtn == 0) {
|
||||
DrawUtils::drawRect(16, index, SCREEN_WIDTH - 16 * 2, 44, 4, COLOR_BORDER_HIGHLIGHTED);
|
||||
regionText = string_format("%s%s%s", curRegionIndex > 0 ? "< " : " ", regionText.c_str(), curRegionIndex < region_map.size() - 1 ? " >" : "").c_str();
|
||||
regionText = string_format("%s%s%s", curRegionIndex > 0 ? "< " : " ", regionText.c_str(), curRegionIndex < (int32_t) region_map.size() - 1 ? " >" : "");
|
||||
} else {
|
||||
DrawUtils::drawRect(16, index, SCREEN_WIDTH - 16 * 2, 44, 2, COLOR_BORDER);
|
||||
}
|
||||
@ -305,7 +304,7 @@ void ConfigUtils::displayMenu() {
|
||||
std::string languageText = lang_map[curSelectedLanguage];
|
||||
if (selectedBtn == 1) {
|
||||
DrawUtils::drawRect(16, index, SCREEN_WIDTH - 16 * 2, 44, 4, COLOR_BORDER_HIGHLIGHTED);
|
||||
languageText = string_format("%s%s%s", curLangIndex > 0 ? "< " : " ", languageText.c_str(), curLangIndex < lang_map.size() - 1 ? " >" : "").c_str();
|
||||
languageText = string_format("%s%s%s", curLangIndex > 0 ? "< " : " ", languageText.c_str(), curLangIndex < (int32_t) lang_map.size() - 1 ? " >" : "");
|
||||
} else {
|
||||
DrawUtils::drawRect(16, index, SCREEN_WIDTH - 16 * 2, 44, 2, COLOR_BORDER);
|
||||
}
|
||||
|
67
src/utils/SettingsUtils.cpp
Normal file
67
src/utils/SettingsUtils.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
#include "SettingsUtils.h"
|
||||
#include "function_patches.h"
|
||||
#include "globals.h"
|
||||
#include "logger.h"
|
||||
#include <coreinit/userconfig.h>
|
||||
#include <cstring>
|
||||
#include <malloc.h>
|
||||
#include <nn/acp/title.h>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
template<typename T>
|
||||
static std::optional<T> readU32FromConfig(std::string_view config_name) {
|
||||
static_assert(sizeof(T) == sizeof(uint32_t), "T must be an enum of size sizeof(uint32_t)");
|
||||
auto ucHandle = UCOpen();
|
||||
std::optional<T> result = {};
|
||||
if (ucHandle >= 0) {
|
||||
UCSysConfig sysConfig = {};
|
||||
uint32_t data = 0xFFFFFFFF;
|
||||
sysConfig.dataType = UC_DATATYPE_UNSIGNED_INT;
|
||||
sysConfig.dataSize = 4;
|
||||
sysConfig.data = &data;
|
||||
strncpy(sysConfig.name, config_name.data(), 64);
|
||||
if (real_UCReadSysConfig(ucHandle, 1, &sysConfig) >= 0) {
|
||||
result = static_cast<T>(*(uint32_t *) sysConfig.data);
|
||||
}
|
||||
UCClose(ucHandle);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<int32_t> getRealCountry() {
|
||||
return readU32FromConfig<uint32_t>("cafe.cntry_reg");
|
||||
}
|
||||
|
||||
std::optional<Languages> getRealLanguage() {
|
||||
return readU32FromConfig<Languages>("cafe.language");
|
||||
}
|
||||
|
||||
std::optional<MCPRegion> getRealRegion() {
|
||||
std::optional<MCPRegion> result = {};
|
||||
auto handle = MCP_Open();
|
||||
if (handle >= 0) {
|
||||
__attribute__((aligned(0x40))) MCPSysProdSettings data;
|
||||
auto res = real_MCP_GetSysProdSettings(handle, &data);
|
||||
if (res >= 0) {
|
||||
result = (MCPRegion) data.product_area;
|
||||
}
|
||||
MCP_Close(handle);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<uint32_t> getRegionForTitle(uint64_t titleId) {
|
||||
auto *acpMetaXml = (ACPMetaXml *) memalign(0x40, sizeof(ACPMetaXml));
|
||||
if (!acpMetaXml) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to alloc memory for ACPMetaXml");
|
||||
return {};
|
||||
}
|
||||
std::optional<uint32_t> result = {};
|
||||
auto res = ACPGetTitleMetaXml(titleId, acpMetaXml);
|
||||
if (res >= 0) {
|
||||
result = (uint32_t) acpMetaXml->region;
|
||||
}
|
||||
free(acpMetaXml);
|
||||
return result;
|
||||
}
|
13
src/utils/SettingsUtils.h
Normal file
13
src/utils/SettingsUtils.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "globals.h"
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
std::optional<int32_t> getRealCountry();
|
||||
|
||||
std::optional<Languages> getRealLanguage();
|
||||
|
||||
std::optional<MCPRegion> getRealRegion();
|
||||
|
||||
std::optional<uint32_t> getRegionForTitle(uint64_t titleId);
|
322
src/utils/WUPSConfigUtils.cpp
Normal file
322
src/utils/WUPSConfigUtils.cpp
Normal file
@ -0,0 +1,322 @@
|
||||
#include "WUPSConfigUtils.h"
|
||||
#include "globals.h"
|
||||
#include "logger.h"
|
||||
#include <wups/config/WUPSConfigItemBoolean.h>
|
||||
#include <wups/config/WUPSConfigItemMultipleValues.h>
|
||||
#include <wups/storage.h>
|
||||
|
||||
#define CAT_GENERAL_ROOT "root"
|
||||
#define CAT_GENERAL_SETTINGS "general_settings"
|
||||
#define CAT_TITLE_SETTINGS "title_settings"
|
||||
|
||||
#define VAL_LANGUAGE "language"
|
||||
#define VAL_COUNTRY "cntry_reg"
|
||||
#define VAL_PRODUCT_AREA "product_area"
|
||||
|
||||
#define VAL_SKIP_OWN_REGION "skip_own_region"
|
||||
#define VAL_PREFER_SYSTEM_SETTINGS "prefer_system_settings"
|
||||
#define VAL_AUTO_DETECTION "auto_detection"
|
||||
#define VAL_DEFAULT_LANG_EUR "default_lang_eur"
|
||||
#define VAL_DEFAULT_LANG_USA "default_lang_usa"
|
||||
#define VAL_DEFAULT_LANG_JPN "default_lang_jpn"
|
||||
|
||||
#define VAL_DEFAULT_COUNTRY_EUR "default_cntry_reg_eur"
|
||||
#define VAL_DEFAULT_COUNTRY_USA "default_cntry_reg_usa"
|
||||
#define VAL_DEFAULT_COUNTRY_JPN "default_cntry_reg_jpn"
|
||||
|
||||
|
||||
const char *countryCodeMap[] = {
|
||||
NULL, "JP", NULL, NULL, NULL, NULL, NULL, NULL, "AI", "AG", "AR",
|
||||
"AW", "BS", "BB", "BZ", "BO", "BR", "VG", "CA", "KY", "CL",
|
||||
"CO", "CR", "DM", "DO", "EC", "SV", "GF", "GD", "GP", "GT",
|
||||
"GY", "HT", "HN", "JM", "MQ", "MX", "MS", "AN", "NI", "PA",
|
||||
"PY", "PE", "KN", "LC", "VC", "SR", "TT", "TC", "US", "UY",
|
||||
"VI", "VE", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, "AL", "AU", "AT", "BE", "BA", "BW", "BG",
|
||||
"HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", "HU",
|
||||
"IS", "IE", "IT", "LV", "LS", "LI", "LT", "LU", "MK", "MT",
|
||||
"ME", "MZ", "NA", "NL", "NZ", "NO", "PL", "PT", "RO", "RU",
|
||||
"RS", "SK", "SI", "ZA", "ES", "SZ", "SE", "CH", "TR", "GB",
|
||||
"ZM", "ZW", "AZ", "MR", "ML", "NE", "TD", "SD", "ER", "DJ",
|
||||
"SO", "AD", "GI", "GG", "IM", "JE", "MC", "TW", NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, "KR", NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, "HK", "MO", NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, "ID", "SG", "TH", "PH", "MY", NULL, NULL, NULL, "CN",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, "AE", NULL, "EG",
|
||||
"OM", "QA", "KW", "SA", "SY", "BH", "JO", NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, "SM", "VA", "BM", "IN", NULL, NULL, NULL,
|
||||
NULL, "NG", "AO", "GH", NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
|
||||
|
||||
static std::optional<WUPSStorageSubItem> rootSettingsStorage = {};
|
||||
static std::optional<WUPSStorageSubItem> titleSettingsStorage = {};
|
||||
static std::optional<WUPSStorageSubItem> generalSettingsStorage = {};
|
||||
|
||||
std::optional<TitleRegionInfo> getTitleRegionInfo(uint64_t titleId, Languages default_language, MCPRegion default_product_area, bool allow_default) {
|
||||
if (!titleSettingsStorage) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to read title settings from storage");
|
||||
return {};
|
||||
}
|
||||
char buffer[18];
|
||||
snprintf(buffer, 17, "%016llX", titleId);
|
||||
|
||||
WUPSStorageError storageError;
|
||||
auto curTitle = titleSettingsStorage->GetSubItem(buffer, storageError);
|
||||
if (!curTitle) {
|
||||
if (storageError == WUPS_STORAGE_ERROR_NOT_FOUND) {
|
||||
if (allow_default) {
|
||||
curTitle = titleSettingsStorage->CreateSubItem(buffer, storageError);
|
||||
} else {
|
||||
// If we don't allow default values, we return now.
|
||||
return {};
|
||||
}
|
||||
}
|
||||
if (!curTitle) {
|
||||
DEBUG_FUNCTION_LINE_ERR("titleSettingsStorage->GetOrCreateSubItem(%s) failed: %s", buffer, WUPSStorageAPI_GetStatusStr(storageError));
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
Languages languages = default_language;
|
||||
MCPRegion product_area = default_product_area;
|
||||
|
||||
storageError = curTitle->GetOrStoreDefault(VAL_LANGUAGE, languages, gCurrentLanguage);
|
||||
if (storageError != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or store language for title %s: %s", buffer, WUPSStorageAPI_GetStatusStr(storageError));
|
||||
return {};
|
||||
}
|
||||
storageError = curTitle->GetOrStoreDefault(VAL_PRODUCT_AREA, product_area, gCurrentProductArea);
|
||||
if (storageError != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or store product area for title %s: %s", buffer, WUPSStorageAPI_GetStatusStr(storageError));
|
||||
return {};
|
||||
}
|
||||
|
||||
return TitleRegionInfo(titleId, languages, product_area);
|
||||
}
|
||||
|
||||
bool saveTitleRegionInfo(const TitleRegionInfo &titleRegionInfo) {
|
||||
if (!titleSettingsStorage) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to read title settings from storage");
|
||||
return false;
|
||||
}
|
||||
char buffer[18];
|
||||
snprintf(buffer, 17, "%016llX", titleRegionInfo.titleId);
|
||||
|
||||
WUPSStorageError storageError;
|
||||
auto curTitle = titleSettingsStorage->GetOrCreateSubItem(buffer, storageError);
|
||||
|
||||
if (!curTitle) {
|
||||
DEBUG_FUNCTION_LINE_ERR("titleSettingsStorage->GetOrCreateSubItem(%s) failed: %s", buffer, WUPSStorageAPI_GetStatusStr(storageError));
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((storageError = curTitle->Store(VAL_LANGUAGE, titleRegionInfo.language)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("curTitle->Store: VAL_LANGUAGE, %s, %d failed: %s", buffer, titleRegionInfo.language, WUPSStorageAPI_GetStatusStr(storageError));
|
||||
}
|
||||
if ((storageError = curTitle->Store(VAL_PRODUCT_AREA, titleRegionInfo.product_area)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("curTitle->Store: VAL_PRODUCT_AREA, %s, %d failed: %s", buffer, titleRegionInfo.product_area, WUPSStorageAPI_GetStatusStr(storageError));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void bool_item_changed(ConfigItemBoolean *item, bool newValue) {
|
||||
DEBUG_FUNCTION_LINE("Value changed for %s: %d", item->identifier ? item->identifier : "[UNKNOWN]", newValue);
|
||||
|
||||
if (std::string_view(VAL_AUTO_DETECTION) == item->identifier) {
|
||||
gAutoDetection = newValue;
|
||||
if (generalSettingsStorage) {
|
||||
generalSettingsStorage->Store(VAL_AUTO_DETECTION, gAutoDetection);
|
||||
}
|
||||
} else if (std::string_view(VAL_PREFER_SYSTEM_SETTINGS) == item->identifier) {
|
||||
gPreferSystemSettings = newValue;
|
||||
if (generalSettingsStorage) {
|
||||
generalSettingsStorage->Store(VAL_PREFER_SYSTEM_SETTINGS, gPreferSystemSettings);
|
||||
}
|
||||
} else if (std::string_view(VAL_SKIP_OWN_REGION) == item->identifier) {
|
||||
gSkipOwnRegion = newValue;
|
||||
if (generalSettingsStorage) {
|
||||
generalSettingsStorage->Store(VAL_SKIP_OWN_REGION, gSkipOwnRegion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void default_lang_changed(ConfigItemMultipleValues *item, uint32_t newValue) {
|
||||
DEBUG_FUNCTION_LINE("New value in %s changed: %d", item->identifier, newValue);
|
||||
|
||||
if (std::string_view(VAL_DEFAULT_LANG_EUR) == item->identifier) {
|
||||
DEBUG_FUNCTION_LINE("Updated default eur lang");
|
||||
gDefaultLangForEUR = (Languages) newValue;
|
||||
} else if (std::string_view(VAL_DEFAULT_LANG_USA) == item->identifier) {
|
||||
DEBUG_FUNCTION_LINE("Updated default usa lang");
|
||||
gDefaultLangForUSA = (Languages) newValue;
|
||||
} else if (std::string_view(VAL_DEFAULT_LANG_JPN) == item->identifier) {
|
||||
DEBUG_FUNCTION_LINE("Updated default jpn lang");
|
||||
gDefaultLangForJPN = (Languages) newValue;
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_WARN("Unexpected identifier for default_lang_changed");
|
||||
return;
|
||||
}
|
||||
if (generalSettingsStorage) {
|
||||
generalSettingsStorage->Store(item->identifier, (int32_t) newValue);
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to store into general settings: sub-item was nullopt");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
static void default_country_changed(ConfigItemMultipleValues *item, uint32_t newValue) {
|
||||
DEBUG_FUNCTION_LINE("New value in %s changed: %d", item->identifier, newValue);
|
||||
|
||||
if (std::string_view(VAL_DEFAULT_COUNTRY_EUR) == item->identifier) {
|
||||
DEBUG_FUNCTION_LINE("Updated default eur country");
|
||||
gDefaultCountryForEUR = (int32_t) newValue;
|
||||
} else if (std::string_view(VAL_DEFAULT_COUNTRY_USA) == item->identifier) {
|
||||
DEBUG_FUNCTION_LINE("Updated default usa country");
|
||||
gDefaultCountryForUSA = (int32_t) newValue;
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_WARN("Unexpected identifier for default_lang_changed");
|
||||
return;
|
||||
}
|
||||
if (generalSettingsStorage) {
|
||||
generalSettingsStorage->Store(item->identifier, (int32_t) newValue);
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to store into general settings: sub-item was nullopt");
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static WUPSConfigAPICallbackStatus ConfigMenuOpenedCallback(WUPSConfigCategoryHandle rootHandle) {
|
||||
try {
|
||||
WUPSConfigCategory root = WUPSConfigCategory(rootHandle);
|
||||
|
||||
root.add(WUPSConfigItemBoolean::Create(VAL_AUTO_DETECTION, "Auto detect region/language",
|
||||
DEFAULT_AUTO_DETECTION_VALUE, gAutoDetection,
|
||||
&bool_item_changed));
|
||||
root.add(WUPSConfigItemBoolean::Create(VAL_SKIP_OWN_REGION, "Force auto detection for in-region titles",
|
||||
DEFAULT_SKIP_OWN_REGION, gSkipOwnRegion,
|
||||
&bool_item_changed));
|
||||
root.add(WUPSConfigItemBoolean::Create(VAL_PREFER_SYSTEM_SETTINGS, "Prefer system settings for in-region titles",
|
||||
DEFAULT_PREFER_SYSTEM_SETTINGS, gPreferSystemSettings,
|
||||
&bool_item_changed));
|
||||
|
||||
constexpr WUPSConfigItemMultipleValues::ValuePair eur_lang_map[] = {
|
||||
{LANG_ENGLISH, "English"},
|
||||
{LANG_FRANCAIS, "Francais"},
|
||||
{LANG_DEUTSCH, "Deutsch"},
|
||||
{LANG_ITALIANO, "Italiano"},
|
||||
{LANG_ESPANOL, "Espanol"},
|
||||
{LANG_NEDERLANDS, "Nederlands"},
|
||||
{LANG_PORTUGUES, "Portugues"},
|
||||
{LANG_RUSSKI, "Russki"},
|
||||
};
|
||||
|
||||
root.add(WUPSConfigItemMultipleValues::CreateFromValue(VAL_DEFAULT_LANG_EUR, "Default language for EUR",
|
||||
DEFAULT_LANG_FOR_EUR, gDefaultLangForEUR,
|
||||
eur_lang_map,
|
||||
default_lang_changed));
|
||||
|
||||
constexpr WUPSConfigItemMultipleValues::ValuePair usa_lang_map[] = {
|
||||
{LANG_ENGLISH, "English"},
|
||||
{LANG_FRANCAIS, "Francais"},
|
||||
{LANG_ESPANOL, "Espanol"},
|
||||
{LANG_PORTUGUES, "Portugues"}};
|
||||
|
||||
root.add(WUPSConfigItemMultipleValues::CreateFromValue(VAL_DEFAULT_LANG_USA, "Default language for USA",
|
||||
DEFAULT_LANG_FOR_USA, gDefaultLangForUSA,
|
||||
usa_lang_map,
|
||||
default_lang_changed));
|
||||
|
||||
/*
|
||||
auto expertCat = WUPSConfigCategory::Create("Expert parameters");
|
||||
std::vector<WUPSConfigItemMultipleValues::ValuePair> valid_country_codes_map;
|
||||
for (uint32_t i = 0; i < sizeof(countryCodeMap) / sizeof(countryCodeMap[0]); i++) {
|
||||
if (countryCodeMap[i] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
valid_country_codes_map.push_back({i, countryCodeMap[i]});
|
||||
}
|
||||
expertCat.add(WUPSConfigItemMultipleValues::CreateFromValue(VAL_DEFAULT_COUNTRY_USA, "Default country for USA (out-of-region titles only)",
|
||||
DEFAULT_COUNTRY_FOR_USA, gDefaultCountryForUSA,
|
||||
valid_country_codes_map,
|
||||
default_country_changed));
|
||||
|
||||
expertCat.add(WUPSConfigItemMultipleValues::CreateFromValue(VAL_DEFAULT_COUNTRY_EUR, "Default country for EUR (out-of-region titles only)",
|
||||
DEFAULT_COUNTRY_FOR_EUR, gDefaultCountryForEUR,
|
||||
valid_country_codes_map,
|
||||
default_country_changed));
|
||||
root.add(std::move(expertCat));
|
||||
*/
|
||||
} catch (std::exception &e) {
|
||||
OSReport("Exception: %s\n", e.what());
|
||||
return WUPSCONFIG_API_CALLBACK_RESULT_ERROR;
|
||||
}
|
||||
return WUPSCONFIG_API_CALLBACK_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static void ConfigMenuClosedCallback() {
|
||||
// Save all changes
|
||||
WUPSStorageError storageError;
|
||||
if ((storageError = WUPSStorageAPI::SaveStorage()) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to save storage: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
}
|
||||
|
||||
void InitConfigAndStorage() {
|
||||
WUPSConfigAPIOptionsV1 configOptions = {.name = "Region Free Plugin"};
|
||||
if (WUPSConfigAPI_Init(configOptions, ConfigMenuOpenedCallback, ConfigMenuClosedCallback) != WUPSCONFIG_API_RESULT_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to init config api");
|
||||
}
|
||||
|
||||
WUPSStorageError storageError;
|
||||
rootSettingsStorage = WUPSStorageAPI::GetOrCreateSubItem(CAT_GENERAL_ROOT, storageError);
|
||||
if (!rootSettingsStorage) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or create %s subitem", CAT_GENERAL_ROOT);
|
||||
}
|
||||
|
||||
titleSettingsStorage = rootSettingsStorage->GetOrCreateSubItem(CAT_TITLE_SETTINGS, storageError);
|
||||
if (!titleSettingsStorage) {
|
||||
DEBUG_FUNCTION_LINE_ERR("WUPS_CreateSubItem %s failed", CAT_TITLE_SETTINGS);
|
||||
}
|
||||
|
||||
|
||||
generalSettingsStorage = rootSettingsStorage->GetOrCreateSubItem(CAT_GENERAL_SETTINGS, storageError);
|
||||
if (!generalSettingsStorage) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or create %s subitem", CAT_GENERAL_SETTINGS);
|
||||
} else {
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_AUTO_DETECTION, gAutoDetection, DEFAULT_AUTO_DETECTION_VALUE)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_PREFER_SYSTEM_SETTINGS, gPreferSystemSettings, DEFAULT_PREFER_SYSTEM_SETTINGS)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_SKIP_OWN_REGION, gSkipOwnRegion, DEFAULT_SKIP_OWN_REGION)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_DEFAULT_LANG_EUR, gDefaultLangForEUR, DEFAULT_LANG_FOR_EUR)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_DEFAULT_COUNTRY_EUR, gDefaultCountryForEUR, DEFAULT_COUNTRY_FOR_EUR)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_DEFAULT_LANG_USA, gDefaultLangForUSA, DEFAULT_LANG_FOR_USA)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_DEFAULT_COUNTRY_USA, gDefaultCountryForUSA, DEFAULT_COUNTRY_FOR_USA)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_DEFAULT_LANG_JPN, gDefaultLangForJPN, DEFAULT_LANG_FOR_JPN)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
if ((storageError = generalSettingsStorage->GetOrStoreDefault(VAL_DEFAULT_COUNTRY_JPN, gDefaultCountryForJPN, DEFAULT_COUNTRY_FOR_JPN)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to get or store default: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
}
|
||||
|
||||
if ((storageError = WUPSStorageAPI::SaveStorage()) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to save storage: %s", WUPSStorageAPI::GetStatusStr(storageError).data());
|
||||
}
|
||||
}
|
18
src/utils/WUPSConfigUtils.h
Normal file
18
src/utils/WUPSConfigUtils.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "globals.h"
|
||||
#include <coreinit/mcp.h>
|
||||
#include <memory>
|
||||
#include <wups/config.h>
|
||||
|
||||
typedef struct TitleRegionInfo {
|
||||
uint64_t titleId;
|
||||
Languages language;
|
||||
MCPRegion product_area;
|
||||
} TitleRegionInfo;
|
||||
|
||||
std::optional<TitleRegionInfo> getTitleRegionInfo(uint64_t titleId, Languages default_language, MCPRegion default_product_area, bool allow_default_values);
|
||||
|
||||
bool saveTitleRegionInfo(const TitleRegionInfo &titleRegionInfo);
|
||||
|
||||
void InitConfigAndStorage();
|
Loading…
Reference in New Issue
Block a user