mirror of
https://github.com/wiiu-env/AromaBasePlugin.git
synced 2024-11-16 17:19:16 +01:00
Compare commits
No commits in common. "main" and "v0.1.1" have entirely different histories.
10
.github/dependabot.yml
vendored
10
.github/dependabot.yml
vendored
@ -1,10 +0,0 @@
|
|||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "docker"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
|||||||
clang-format:
|
clang-format:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
- name: clang-format
|
- name: clang-format
|
||||||
run: |
|
run: |
|
||||||
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./src --exclude ./src/utils/json.hpp
|
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./src --exclude ./src/utils/json.hpp
|
||||||
@ -17,7 +17,7 @@ jobs:
|
|||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
needs: clang-format
|
needs: clang-format
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
- name: create version.h
|
- name: create version.h
|
||||||
run: |
|
run: |
|
||||||
git_hash=$(git rev-parse --short "$GITHUB_SHA")
|
git_hash=$(git rev-parse --short "$GITHUB_SHA")
|
||||||
@ -48,7 +48,7 @@ jobs:
|
|||||||
- name: zip artifact
|
- name: zip artifact
|
||||||
run: zip -r ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip *.wps
|
run: zip -r ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip *.wps
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
uses: "softprops/action-gh-release@v2"
|
uses: "softprops/action-gh-release@v1"
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
|
tag_name: ${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
|
||||||
draft: false
|
draft: false
|
||||||
|
4
.github/workflows/pr.yml
vendored
4
.github/workflows/pr.yml
vendored
@ -6,7 +6,7 @@ jobs:
|
|||||||
clang-format:
|
clang-format:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
- name: clang-format
|
- name: clang-format
|
||||||
run: |
|
run: |
|
||||||
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./src --exclude ./src/utils/json.hpp
|
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./src --exclude ./src/utils/json.hpp
|
||||||
@ -14,7 +14,7 @@ jobs:
|
|||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
needs: clang-format
|
needs: clang-format
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
- name: create version.h
|
- name: create version.h
|
||||||
run: |
|
run: |
|
||||||
git_hash=$(git rev-parse --short "${{ github.event.pull_request.head.sha }}")
|
git_hash=$(git rev-parse --short "${{ github.event.pull_request.head.sha }}")
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,4 +7,3 @@ sysapp.cbp
|
|||||||
.idea/
|
.idea/
|
||||||
cmake-build-debug/
|
cmake-build-debug/
|
||||||
CMakeLists.txt
|
CMakeLists.txt
|
||||||
*.zip
|
|
||||||
|
12
Dockerfile
12
Dockerfile
@ -1,10 +1,8 @@
|
|||||||
FROM ghcr.io/wiiu-env/devkitppc:20240505
|
FROM ghcr.io/wiiu-env/devkitppc:20230218
|
||||||
|
|
||||||
COPY --from=ghcr.io/wiiu-env/wiiupluginsystem:20240505 /artifacts $DEVKITPRO
|
COPY --from=ghcr.io/wiiu-env/wiiupluginsystem:20230215 /artifacts $DEVKITPRO
|
||||||
COPY --from=ghcr.io/wiiu-env/libnotifications:20240426 /artifacts $DEVKITPRO
|
COPY --from=ghcr.io/wiiu-env/libnotifications:20230126 /artifacts $DEVKITPRO
|
||||||
COPY --from=ghcr.io/wiiu-env/librpxloader:20240425 /artifacts $DEVKITPRO
|
COPY --from=ghcr.io/wiiu-env/librpxloader:20220903 /artifacts $DEVKITPRO
|
||||||
COPY --from=ghcr.io/wiiu-env/libcurlwrapper:20240505 /artifacts $DEVKITPRO
|
COPY --from=ghcr.io/wiiu-env/libcurlwrapper:20230121 /artifacts $DEVKITPRO
|
||||||
COPY --from=ghcr.io/wiiu-env/libsdutils:20230621 /artifacts $DEVKITPRO
|
|
||||||
COPY --from=ghcr.io/wiiu-env/libmocha:20231127 /artifacts $DEVKITPRO
|
|
||||||
|
|
||||||
WORKDIR project
|
WORKDIR project
|
4
Makefile
4
Makefile
@ -48,13 +48,13 @@ CXXFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
|||||||
CFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
CFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LIBS := -lmocha -lcurlwrapper -lnotifications -lrpxloader -lsdutils -lwups -lwut
|
LIBS := -lcurlwrapper -lnotifications -lrpxloader -lwups -lwut
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# list of directories containing libraries, this must be the top level
|
# list of directories containing libraries, this must be the top level
|
||||||
# containing include and lib
|
# containing include and lib
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
LIBDIRS := $(PORTLIBS) $(WUPS_ROOT) $(WUMS_ROOT) $(WUT_ROOT) $(WUT_ROOT)/usr
|
LIBDIRS := $(PORTLIBS) $(WUPS_ROOT) $(WUMS_ROOT) $(WUT_ROOT)
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# no real need to edit anything past this point unless you need to add additional
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
@ -11,7 +11,6 @@ Provides some simple patches for Wii U Menu and checks for Aroma updates.
|
|||||||
3. Requires the [CURLWrapperModule](https://github.com/wiiu-env/CURLWrapperModule) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
|
3. Requires the [CURLWrapperModule](https://github.com/wiiu-env/CURLWrapperModule) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
|
||||||
4. Requires the [NotificationModule](https://github.com/wiiu-env/NotificationModule) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
|
4. Requires the [NotificationModule](https://github.com/wiiu-env/NotificationModule) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
|
||||||
5. Requires the [RPXLoadingModule](https://github.com/wiiu-env/RPXLoadingModule) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
|
5. Requires the [RPXLoadingModule](https://github.com/wiiu-env/RPXLoadingModule) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
|
||||||
6. Requires the [SDHotSwapModule](https://github.com/wiiu-env/SDHotSwapModule) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@ -35,8 +34,6 @@ For building you need:
|
|||||||
- [libnotifications](https://github.com/wiiu-env/libnotifications)
|
- [libnotifications](https://github.com/wiiu-env/libnotifications)
|
||||||
- [librpxloader](https://github.com/wiiu-env/librpxloader)
|
- [librpxloader](https://github.com/wiiu-env/librpxloader)
|
||||||
- [libcurlwrapper](https://github.com/wiiu-env/libcurlwrapper)
|
- [libcurlwrapper](https://github.com/wiiu-env/libcurlwrapper)
|
||||||
- [libsdutils](https://github.com/wiiu-env/libsdutils)
|
|
||||||
- [libmocha](https://github.com/wiiu-env/libmocha)
|
|
||||||
|
|
||||||
## Building using the Dockerfile
|
## Building using the Dockerfile
|
||||||
|
|
||||||
|
@ -4,16 +4,11 @@
|
|||||||
#include <coreinit/thread.h>
|
#include <coreinit/thread.h>
|
||||||
#include <notifications/notification_defines.h>
|
#include <notifications/notification_defines.h>
|
||||||
#include <notifications/notifications.h>
|
#include <notifications/notifications.h>
|
||||||
#include <sdutils/sdutils.h>
|
|
||||||
#include <sys/fcntl.h>
|
|
||||||
#include <sys/unistd.h>
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
std::unique_ptr<std::thread> sShowHintThread;
|
std::unique_ptr<std::thread> sShowHintThread;
|
||||||
static bool sShutdownHintThread = false;
|
static bool sShutdownHintThread = false;
|
||||||
|
|
||||||
bool SaveHintShownToStorage(bool hintShown);
|
|
||||||
|
|
||||||
void ShowHints() {
|
void ShowHints() {
|
||||||
bool isOverlayReady = false;
|
bool isOverlayReady = false;
|
||||||
while (!sShutdownHintThread &&
|
while (!sShutdownHintThread &&
|
||||||
@ -24,61 +19,38 @@ void ShowHints() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMounted = false;
|
const char *tmp_file = "fs:/vol/external01/wiiu/write_lock";
|
||||||
if (SDUtils_IsSdCardMounted(&isMounted) != SDUTILS_RESULT_SUCCESS) {
|
int fd = -1;
|
||||||
DEBUG_FUNCTION_LINE_ERR("SDUtils_IsSdCardMounted failed");
|
if ((fd = open(tmp_file, O_CREAT | O_TRUNC | O_RDWR)) < 0) {
|
||||||
}
|
NotificationModuleStatus err;
|
||||||
|
NMColor red = {237, 28, 36, 255};
|
||||||
if (isMounted) {
|
NotificationModuleHandle outHandle;
|
||||||
const char *tmp_file = "fs:/vol/external01/wiiu/write_lock";
|
if ((err = NotificationModule_SetDefaultValue(NOTIFICATION_MODULE_NOTIFICATION_TYPE_DYNAMIC, NOTIFICATION_MODULE_DEFAULT_OPTION_BACKGROUND_COLOR, red)) == NOTIFICATION_MODULE_RESULT_SUCCESS &&
|
||||||
int fd = -1;
|
(err = NotificationModule_AddDynamicNotification("Failed to write to the sd card. Please restart the console and make sure the sd card is not write locked.", &outHandle)) == NOTIFICATION_MODULE_RESULT_SUCCESS) {
|
||||||
if ((fd = open(tmp_file, O_CREAT | O_TRUNC | O_RDWR)) < 0) {
|
|
||||||
DEBUG_FUNCTION_LINE_WARN("SD Card mounted but not writable. errno: %d", errno);
|
|
||||||
NotificationModuleStatus err;
|
|
||||||
NMColor red = {237, 28, 36, 255};
|
|
||||||
NotificationModuleHandle outHandle;
|
|
||||||
if ((err = NotificationModule_SetDefaultValue(NOTIFICATION_MODULE_NOTIFICATION_TYPE_DYNAMIC, NOTIFICATION_MODULE_DEFAULT_OPTION_BACKGROUND_COLOR, red)) != NOTIFICATION_MODULE_RESULT_SUCCESS ||
|
|
||||||
(err = NotificationModule_AddDynamicNotification("Failed to write to the sd card. Please restart the console and make sure the sd card is not write locked.", &outHandle)) != NOTIFICATION_MODULE_RESULT_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to display notification: %s", NotificationModule_GetStatusStr(err));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("SD Card is mounted and writeable");
|
|
||||||
close(fd);
|
|
||||||
remove(tmp_file);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("SD Card is not mounted");
|
close(fd);
|
||||||
|
remove(tmp_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gConfigMenuHintShown) {
|
if (!gConfigMenuHintShown) {
|
||||||
NotificationModuleStatus err;
|
NotificationModuleStatus err;
|
||||||
if ((err = NotificationModule_SetDefaultValue(NOTIFICATION_MODULE_NOTIFICATION_TYPE_INFO, NOTIFICATION_MODULE_DEFAULT_OPTION_DURATION_BEFORE_FADE_OUT, 15.0f)) == NOTIFICATION_MODULE_RESULT_SUCCESS &&
|
if ((err = NotificationModule_SetDefaultValue(NOTIFICATION_MODULE_NOTIFICATION_TYPE_INFO, NOTIFICATION_MODULE_DEFAULT_OPTION_DURATION_BEFORE_FADE_OUT, 15.0f)) == NOTIFICATION_MODULE_RESULT_SUCCESS &&
|
||||||
(err = NotificationModule_AddInfoNotification("Tip: You can open a configuration menu by pressing \ue052 + \ue07A + \ue046")) == NOTIFICATION_MODULE_RESULT_SUCCESS) {
|
(err = NotificationModule_AddInfoNotification("Tip: You can open a configuration menu by pressing \ue052 + \ue07A + \ue046")) == NOTIFICATION_MODULE_RESULT_SUCCESS) {
|
||||||
|
if (WUPS_OpenStorage() == WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
gConfigMenuHintShown = true;
|
gConfigMenuHintShown = true;
|
||||||
SaveHintShownToStorage(gConfigMenuHintShown);
|
wups_storage_item_t *cat_other = nullptr;
|
||||||
|
if (WUPS_GetSubItem(nullptr, CAT_OTHER, &cat_other) == WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
|
WUPS_StoreInt(cat_other, CONFIG_MENU_HINT_SHOWN_ID, gConfigMenuHintShown);
|
||||||
|
}
|
||||||
|
WUPS_CloseStorage();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to show Notification: %d %s", err, NotificationModule_GetStatusStr(err));
|
DEBUG_FUNCTION_LINE_ERR("Failed to show Notification: %d %s", err, NotificationModule_GetStatusStr(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SaveHintShownToStorage(bool hintShown) {
|
|
||||||
WUPSStorageError storageError;
|
|
||||||
auto subItem = WUPSStorageAPI::GetSubItem(CAT_OTHER, storageError);
|
|
||||||
if (!subItem) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get sub category");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
storageError = subItem->Store(CONFIG_MENU_HINT_SHOWN_ID, hintShown);
|
|
||||||
if (storageError != WUPS_STORAGE_ERROR_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to store hint shown");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return WUPSStorageAPI::SaveStorage() == WUPS_STORAGE_ERROR_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StartHintThread() {
|
void StartHintThread() {
|
||||||
sShowHintThread.reset();
|
sShowHintThread.reset();
|
||||||
sShutdownHintThread = false;
|
sShutdownHintThread = false;
|
||||||
|
@ -11,18 +11,14 @@
|
|||||||
#include <padscore/wpad.h>
|
#include <padscore/wpad.h>
|
||||||
#include <rpxloader/rpxloader.h>
|
#include <rpxloader/rpxloader.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vpad/input.h>
|
#include <vpad/input.h>
|
||||||
#include <wups/function_patching.h>
|
|
||||||
|
|
||||||
static std::string sAromaUpdaterPath = AROMA_UPDATER_NEW_PATH_FULL;
|
|
||||||
static NotificationModuleHandle sAromaUpdateHandle = 0;
|
static NotificationModuleHandle sAromaUpdateHandle = 0;
|
||||||
std::unique_ptr<std::thread> sCheckUpdateThread;
|
std::unique_ptr<std::thread> sCheckUpdateThread;
|
||||||
static bool sShutdownUpdateThread = false;
|
static bool sShutdownUpdateThread = false;
|
||||||
void UpdateCheckThreadEntry();
|
void UpdateCheckThreadEntry();
|
||||||
|
|
||||||
void ShowUpdateNotification();
|
|
||||||
constexpr uint32_t HIDE_UPDATE_WARNING_VPAD_COMBO = VPAD_BUTTON_MINUS;
|
constexpr uint32_t HIDE_UPDATE_WARNING_VPAD_COMBO = VPAD_BUTTON_MINUS;
|
||||||
constexpr uint32_t LAUNCH_AROMA_UPDATER_VPAD_COMBO = VPAD_BUTTON_PLUS;
|
constexpr uint32_t LAUNCH_AROMA_UPDATER_VPAD_COMBO = VPAD_BUTTON_PLUS;
|
||||||
constexpr uint32_t sHoldForFramesTarget = 60;
|
constexpr uint32_t sHoldForFramesTarget = 60;
|
||||||
@ -45,26 +41,6 @@ void StopUpdaterCheckThread() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool saveLatestUpdateHash(const std::string &hash) {
|
|
||||||
WUPSStorageError err;
|
|
||||||
auto subItem = WUPSStorageAPI::GetSubItem(CAT_OTHER, err);
|
|
||||||
if (!subItem) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get sub category");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (subItem->Store(LAST_UPDATE_HASH_ID, hash) != WUPS_STORAGE_ERROR_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to store latest update hash");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WUPSStorageAPI::SaveStorage() != WUPS_STORAGE_ERROR_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to save storage");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateCheckThreadEntry() {
|
void UpdateCheckThreadEntry() {
|
||||||
bool isOverlayReady = false;
|
bool isOverlayReady = false;
|
||||||
while (!sShutdownUpdateThread &&
|
while (!sShutdownUpdateThread &&
|
||||||
@ -81,51 +57,45 @@ void UpdateCheckThreadEntry() {
|
|||||||
std::string errorTextOut;
|
std::string errorTextOut;
|
||||||
float progress;
|
float progress;
|
||||||
|
|
||||||
if (DownloadUtils::DownloadFileToBuffer(AROMA_UPDATER_LAST_UPDATE_URL, outBuffer, responseCodeOut, errorOut, errorTextOut, &progress) != 0) {
|
if (DownloadUtils::DownloadFileToBuffer(AROMA_UPDATER_LAST_UPDATE_URL, outBuffer, responseCodeOut, errorOut, errorTextOut, &progress) == 0) {
|
||||||
DEBUG_FUNCTION_LINE_INFO("Download failed: %d %s", errorOut, errorTextOut.c_str());
|
try {
|
||||||
return;
|
AromaUpdater::LatestVersion data = nlohmann::json::parse(outBuffer);
|
||||||
}
|
gUpdateChecked = true;
|
||||||
try {
|
if (gLastHash.empty()) { // don't show update warning on first boot
|
||||||
AromaUpdater::LatestVersion data = nlohmann::json::parse(outBuffer);
|
gLastHash = data.getHash();
|
||||||
gUpdateChecked = true;
|
} else if (gLastHash != data.getHash()) {
|
||||||
|
struct stat st {};
|
||||||
|
if (stat(AROMA_UPDATER_PATH_FULL, &st) >= 0 && S_ISREG(st.st_mode)) {
|
||||||
|
NotificationModuleStatus err;
|
||||||
|
if ((err = NotificationModule_AddDynamicNotification("A new Aroma Update is available. "
|
||||||
|
"Hold \ue045 to launch the Aroma Updater, press \ue046 to hide this message",
|
||||||
|
&sAromaUpdateHandle)) != NOTIFICATION_MODULE_RESULT_SUCCESS) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to add update notification. %s", NotificationModule_GetStatusStr(err));
|
||||||
|
sAromaUpdateHandle = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NotificationModule_SetDefaultValue(NOTIFICATION_MODULE_NOTIFICATION_TYPE_INFO, NOTIFICATION_MODULE_DEFAULT_OPTION_DURATION_BEFORE_FADE_OUT, 15.0f);
|
||||||
|
NotificationModule_AddInfoNotification("A new Aroma Update is available. Please launch the Aroma Updater!");
|
||||||
|
}
|
||||||
|
|
||||||
if (gLastHash.empty()) { // don't show update warning on first boot
|
gLastHash = data.getHash();
|
||||||
gLastHash = data.getHash();
|
} else {
|
||||||
} else if (gLastHash != data.getHash()) {
|
DEBUG_FUNCTION_LINE_VERBOSE("We don't need to update the hash");
|
||||||
ShowUpdateNotification();
|
return;
|
||||||
} else if (gLastHash == data.getHash()) {
|
}
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("We don't need to update the hash");
|
|
||||||
return;
|
if (WUPS_OpenStorage() == WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
|
wups_storage_item_t *cat_other = nullptr;
|
||||||
|
if (WUPS_GetSubItem(nullptr, CAT_OTHER, &cat_other) == WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
|
WUPS_StoreString(cat_other, LAST_UPDATE_HASH_ID, gLastHash.c_str());
|
||||||
|
}
|
||||||
|
WUPS_CloseStorage();
|
||||||
|
}
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("Failed to parse AromaUpdater::LatestVersion");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update hash
|
|
||||||
gLastHash = data.getHash();
|
|
||||||
|
|
||||||
saveLatestUpdateHash(gLastHash);
|
|
||||||
} catch (std::exception &e) {
|
|
||||||
DEBUG_FUNCTION_LINE_WARN("Failed to parse AromaUpdater::LatestVersion");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShowUpdateNotification() {
|
|
||||||
struct stat st {};
|
|
||||||
// Check if the Aroma Updater is on the sd card
|
|
||||||
if (stat(AROMA_UPDATER_OLD_PATH_FULL, &st) >= 0 && S_ISREG(st.st_mode)) {
|
|
||||||
sAromaUpdaterPath = AROMA_UPDATER_OLD_PATH;
|
|
||||||
} else if (stat(AROMA_UPDATER_NEW_PATH_FULL, &st) >= 0 && S_ISREG(st.st_mode)) {
|
|
||||||
sAromaUpdaterPath = AROMA_UPDATER_NEW_PATH;
|
|
||||||
} else {
|
} else {
|
||||||
NotificationModule_SetDefaultValue(NOTIFICATION_MODULE_NOTIFICATION_TYPE_INFO, NOTIFICATION_MODULE_DEFAULT_OPTION_DURATION_BEFORE_FADE_OUT, 15.0f);
|
DEBUG_FUNCTION_LINE_INFO("Download failed: %d %s", errorOut, errorTextOut.c_str());
|
||||||
NotificationModule_AddInfoNotification("A new Aroma Update is available. Please launch the Aroma Updater!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NotificationModuleStatus err;
|
|
||||||
if ((err = NotificationModule_AddDynamicNotification("A new Aroma Update is available. "
|
|
||||||
"Hold \ue045 to launch the Aroma Updater, press \ue046 to hide this message",
|
|
||||||
&sAromaUpdateHandle)) != NOTIFICATION_MODULE_RESULT_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to add update notification. %s", NotificationModule_GetStatusStr(err));
|
|
||||||
sAromaUpdateHandle = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,16 +112,15 @@ bool CheckForButtonCombo(uint32_t trigger, uint32_t hold, uint32_t &holdForXFram
|
|||||||
}
|
}
|
||||||
if (hold == LAUNCH_AROMA_UPDATER_VPAD_COMBO) {
|
if (hold == LAUNCH_AROMA_UPDATER_VPAD_COMBO) {
|
||||||
if (++holdForXFrames > holdForFramesTarget) {
|
if (++holdForXFrames > holdForFramesTarget) {
|
||||||
NotificationModule_FinishDynamicNotification(sAromaUpdateHandle, 0.5f);
|
|
||||||
sAromaUpdateHandle = 0;
|
|
||||||
RPXLoaderStatus err;
|
RPXLoaderStatus err;
|
||||||
if ((err = RPXLoader_LaunchHomebrew(sAromaUpdaterPath.c_str())) == RPX_LOADER_RESULT_SUCCESS) {
|
if ((err = RPXLoader_LaunchHomebrew(AROMA_UPDATER_PATH)) == RPX_LOADER_RESULT_SUCCESS) {
|
||||||
updaterLaunched = true;
|
NotificationModule_FinishDynamicNotification(sAromaUpdateHandle, 2.0f);
|
||||||
|
sAromaUpdateHandle = 0;
|
||||||
|
updaterLaunched = true;
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
DEBUG_FUNCTION_LINE_ERR("RPXLoader_LaunchHomebrew failed: %s", RPXLoader_GetStatusStr(err));
|
DEBUG_FUNCTION_LINE_ERR("RPXLoader_LaunchHomebrew failed: %s", RPXLoader_GetStatusStr(err));
|
||||||
NotificationModule_AddErrorNotification("Failed to launch Aroma Updater");
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
holdForXFrames = 0;
|
holdForXFrames = 0;
|
||||||
@ -189,7 +158,6 @@ DECL_FUNCTION(int32_t, VPADRead, VPADChan chan,
|
|||||||
|
|
||||||
static uint32_t sWPADLastButtonHold[4] = {0, 0, 0, 0};
|
static uint32_t sWPADLastButtonHold[4] = {0, 0, 0, 0};
|
||||||
static uint32_t sHoldForXFramesWPAD[4] = {0, 0, 0, 0};
|
static uint32_t sHoldForXFramesWPAD[4] = {0, 0, 0, 0};
|
||||||
|
|
||||||
DECL_FUNCTION(void, WPADRead, WPADChan chan, WPADStatusProController *data) {
|
DECL_FUNCTION(void, WPADRead, WPADChan chan, WPADStatusProController *data) {
|
||||||
real_WPADRead(chan, data);
|
real_WPADRead(chan, data);
|
||||||
if (!sAromaUpdateHandle) {
|
if (!sAromaUpdateHandle) {
|
||||||
|
16
src/common.h
16
src/common.h
@ -1,13 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#define SD_CARD_PATH "fs:/vol/external01/"
|
#define SD_CARD_PATH "fs:/vol/external01/"
|
||||||
#define AROMA_UPDATER_OLD_PATH "wiiu/apps/AromaUpdater.wuhb"
|
#define AROMA_UPDATER_PATH "wiiu/apps/AromaUpdater.wuhb"
|
||||||
#define AROMA_UPDATER_NEW_DIRECTORY "wiiu/apps/AromaUpdater"
|
#define AROMA_UPDATER_PATH_FULL SD_CARD_PATH AROMA_UPDATER_PATH
|
||||||
#define AROMA_UPDATER_NEW_PATH AROMA_UPDATER_NEW_DIRECTORY "/AromaUpdater.wuhb"
|
#define AROMA_UPDATER_LAST_UPDATE_URL "https://aroma.foryour.cafe/api/latest_version"
|
||||||
#define AROMA_UPDATER_OLD_PATH_FULL SD_CARD_PATH AROMA_UPDATER_OLD_PATH
|
|
||||||
#define AROMA_UPDATER_NEW_PATH_FULL SD_CARD_PATH AROMA_UPDATER_NEW_PATH
|
|
||||||
#define AROMA_UPDATER_NEW_DIRECTORY_FULL SD_CARD_PATH AROMA_UPDATER_NEW_DIRECTORY
|
|
||||||
#define AROMA_UPDATER_LAST_UPDATE_URL "https://aroma.foryour.cafe/api/latest_version"
|
|
||||||
|
|
||||||
|
|
||||||
#define BACKUPS_DIRECTORY "wiiu/backups"
|
|
||||||
#define BACKUPS_DIRECTORY_FULL SD_CARD_PATH BACKUPS_DIRECTORY
|
|
110
src/main.cpp
110
src/main.cpp
@ -4,18 +4,15 @@
|
|||||||
#include "utils/DownloadUtils.h"
|
#include "utils/DownloadUtils.h"
|
||||||
#include "utils/LatestVersion.h"
|
#include "utils/LatestVersion.h"
|
||||||
#include "utils/config.h"
|
#include "utils/config.h"
|
||||||
#include "utils/utils.h"
|
|
||||||
#include <coreinit/title.h>
|
#include <coreinit/title.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <mocha/mocha.h>
|
|
||||||
#include <nn/spm.h>
|
#include <nn/spm.h>
|
||||||
#include <notifications/notifications.h>
|
#include <notifications/notifications.h>
|
||||||
#include <rpxloader/rpxloader.h>
|
#include <rpxloader/rpxloader.h>
|
||||||
#include <sdutils/sdutils.h>
|
|
||||||
#include <utils/logger.h>
|
#include <utils/logger.h>
|
||||||
#include <wups.h>
|
#include <wups.h>
|
||||||
|
|
||||||
WUPS_PLUGIN_NAME("Aroma Base Plugin");
|
WUPS_PLUGIN_NAME("AromaBasePlugin");
|
||||||
WUPS_PLUGIN_DESCRIPTION("Implements small patches and checks for Aroma updates.");
|
WUPS_PLUGIN_DESCRIPTION("Implements small patches and checks for Aroma updates.");
|
||||||
WUPS_PLUGIN_VERSION(PLUGIN_VERSION_FULL);
|
WUPS_PLUGIN_VERSION(PLUGIN_VERSION_FULL);
|
||||||
WUPS_PLUGIN_AUTHOR("Maschell");
|
WUPS_PLUGIN_AUTHOR("Maschell");
|
||||||
@ -24,56 +21,6 @@ WUPS_PLUGIN_LICENSE("GPL");
|
|||||||
WUPS_USE_WUT_DEVOPTAB();
|
WUPS_USE_WUT_DEVOPTAB();
|
||||||
WUPS_USE_STORAGE("aroma_base_plugin"); // Unique id for the storage api
|
WUPS_USE_STORAGE("aroma_base_plugin"); // Unique id for the storage api
|
||||||
|
|
||||||
bool InitConfigValuesFromStorage() {
|
|
||||||
bool result = true;
|
|
||||||
WUPSStorageError storageError;
|
|
||||||
auto subItemConfig = WUPSStorageAPI::GetOrCreateSubItem(CAT_CONFIG, storageError);
|
|
||||||
if (!subItemConfig) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or create sub category \"%s\"", CAT_CONFIG);
|
|
||||||
result = false;
|
|
||||||
} else {
|
|
||||||
if (subItemConfig->GetOrStoreDefault(USTEALTH_CONFIG_ID, gActivateUStealth, ACTIVATE_USTEALTH_DEFAULT) != WUPS_STORAGE_ERROR_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or create item \"%s\"", USTEALTH_CONFIG_ID);
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
if (subItemConfig->GetOrStoreDefault(POWEROFFWARNING_CONFIG_ID, gSkip4SecondOffStatusCheck, SKIP_4_SECOND_OFF_STATUS_CHECK_DEFAULT) != WUPS_STORAGE_ERROR_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or create item \"%s\"", POWEROFFWARNING_CONFIG_ID);
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
if (subItemConfig->GetOrStoreDefault(FORCE_NDM_SUSPEND_SUCCESS_CONFIG_ID, gForceNDMSuspendSuccess, FORCE_NDM_SUSPEND_SUCCESS_DEFAULT) != WUPS_STORAGE_ERROR_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or create item \"%s\"", FORCE_NDM_SUSPEND_SUCCESS_CONFIG_ID);
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
if (subItemConfig->GetOrStoreDefault(ALLOW_ERROR_NOTIFICATIONS, gAllowErrorNotifications, ALLOW_ERROR_NOTIFICATIONS_DEFAULT) != WUPS_STORAGE_ERROR_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or create item \"%s\"", ALLOW_ERROR_NOTIFICATIONS);
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto subItemOther = WUPSStorageAPI::GetOrCreateSubItem(CAT_OTHER, storageError);
|
|
||||||
if (!subItemOther) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or create sub category \"%s\"", CAT_OTHER);
|
|
||||||
result = false;
|
|
||||||
} else {
|
|
||||||
if ((storageError = subItemOther->GetOrStoreDefault(CONFIG_MENU_HINT_SHOWN_ID, gConfigMenuHintShown, CONFIG_MENU_HINT_SHOWN_DEFAULT)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or create item \"%s\": %s", CONFIG_MENU_HINT_SHOWN_ID, WUPSStorageAPI_GetStatusStr(storageError));
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
if ((storageError = subItemOther->GetOrStoreDefault(LAST_UPDATE_HASH_ID, gLastHash, LAST_UPDATE_HASH_DEFAULT)) != WUPS_STORAGE_ERROR_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get or create item \"%s\": %s", LAST_UPDATE_HASH_ID, WUPSStorageAPI_GetStatusStr(storageError));
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WUPSStorageAPI::SaveStorage() != WUPS_STORAGE_ERROR_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to save storage");
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
INITIALIZE_PLUGIN() {
|
INITIALIZE_PLUGIN() {
|
||||||
initLogging();
|
initLogging();
|
||||||
if (NotificationModule_InitLibrary() != NOTIFICATION_MODULE_RESULT_SUCCESS) {
|
if (NotificationModule_InitLibrary() != NOTIFICATION_MODULE_RESULT_SUCCESS) {
|
||||||
@ -82,21 +29,46 @@ INITIALIZE_PLUGIN() {
|
|||||||
if (RPXLoader_InitLibrary() != RPX_LOADER_RESULT_SUCCESS) {
|
if (RPXLoader_InitLibrary() != RPX_LOADER_RESULT_SUCCESS) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("RPXLoader_InitLibrary failed");
|
DEBUG_FUNCTION_LINE_ERR("RPXLoader_InitLibrary failed");
|
||||||
}
|
}
|
||||||
if (SDUtils_InitLibrary() != SDUTILS_RESULT_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("SDUtils_InitLibrary failed");
|
// Open storage to read values
|
||||||
|
WUPSStorageError storageRes = WUPS_OpenStorage();
|
||||||
|
if (storageRes == WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
|
wups_storage_item_t *cat_config = nullptr;
|
||||||
|
if (WUPS_GetSubItem(nullptr, CAT_CONFIG, &cat_config) == WUPS_STORAGE_ERROR_NOT_FOUND) {
|
||||||
|
if (WUPS_CreateSubItem(nullptr, CAT_CONFIG, &cat_config) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
|
cat_config = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cat_config != nullptr) {
|
||||||
|
LOAD_BOOL_FROM_STORAGE(cat_config, USTEALTH_CONFIG_ID, gActivateUStealth);
|
||||||
|
LOAD_BOOL_FROM_STORAGE(cat_config, POWEROFFWARNING_CONFIG_ID, gSkip4SecondOffStatusCheck);
|
||||||
|
LOAD_BOOL_FROM_STORAGE(cat_config, FORCE_NDM_SUSPEND_SUCCESS_CONFIG_ID, gForceNDMSuspendSuccess);
|
||||||
|
LOAD_BOOL_FROM_STORAGE(cat_config, ALLOW_ERROR_NOTIFICATIONS, gAllowErrorNotifications);
|
||||||
|
}
|
||||||
|
|
||||||
|
wups_storage_item_t *cat_other = nullptr;
|
||||||
|
if (WUPS_GetSubItem(nullptr, CAT_OTHER, &cat_other) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
|
if (WUPS_CreateSubItem(nullptr, CAT_OTHER, &cat_other) != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
|
cat_other = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cat_other != nullptr) {
|
||||||
|
LOAD_BOOL_FROM_STORAGE(cat_other, CONFIG_MENU_HINT_SHOWN_ID, gConfigMenuHintShown);
|
||||||
|
char hash[41];
|
||||||
|
memset(hash, 0, sizeof(hash));
|
||||||
|
LOAD_STRING_FROM_STORAGE(cat_other, LAST_UPDATE_HASH_ID, hash, sizeof(hash));
|
||||||
|
gLastHash = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close storage
|
||||||
|
if (WUPS_CloseStorage() != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to close storage");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to open storage %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Mocha_InitLibrary() != MOCHA_RESULT_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Mocha_InitLibrary failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
InitConfigValuesFromStorage();
|
|
||||||
|
|
||||||
InitConfigMenu();
|
|
||||||
|
|
||||||
Utils::MigrateAromaUpdater();
|
|
||||||
|
|
||||||
Utils::DumpOTPAndSeeprom();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ON_APPLICATION_START() {
|
ON_APPLICATION_START() {
|
||||||
@ -114,14 +86,12 @@ ON_APPLICATION_START() {
|
|||||||
ON_APPLICATION_ENDS() {
|
ON_APPLICATION_ENDS() {
|
||||||
StopHintThread();
|
StopHintThread();
|
||||||
StopUpdaterCheckThread();
|
StopUpdaterCheckThread();
|
||||||
DownloadUtils::Deinit();
|
|
||||||
deinitLogging();
|
deinitLogging();
|
||||||
}
|
}
|
||||||
|
|
||||||
DEINITIALIZE_PLUGIN() {
|
DEINITIALIZE_PLUGIN() {
|
||||||
NotificationModule_DeInitLibrary();
|
NotificationModule_DeInitLibrary();
|
||||||
RPXLoader_DeInitLibrary();
|
RPXLoader_DeInitLibrary();
|
||||||
SDUtils_DeInitLibrary();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DECL_FUNCTION(uint32_t, SuspendDaemonsAndDisconnectIfWireless__Q2_2nn3ndmFv) {
|
DECL_FUNCTION(uint32_t, SuspendDaemonsAndDisconnectIfWireless__Q2_2nn3ndmFv) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#define PLUGIN_VERSION "v0.1.6"
|
#define PLUGIN_VERSION "v0.1.1"
|
||||||
#define PLUGIN_VERSION_FULL PLUGIN_VERSION PLUGIN_VERSION_EXTRA
|
#define PLUGIN_VERSION_FULL PLUGIN_VERSION PLUGIN_VERSION_EXTRA
|
||||||
|
@ -1,173 +0,0 @@
|
|||||||
|
|
||||||
#include "CFile.hpp"
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <strings.h>
|
|
||||||
|
|
||||||
CFile::CFile() {
|
|
||||||
iFd = -1;
|
|
||||||
mem_file = nullptr;
|
|
||||||
filesize = 0;
|
|
||||||
pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CFile::CFile(const std::string &filepath, eOpenTypes mode) {
|
|
||||||
iFd = -1;
|
|
||||||
this->open(filepath, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
CFile::CFile(const uint8_t *mem, int32_t size) {
|
|
||||||
iFd = -1;
|
|
||||||
this->open(mem, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
CFile::~CFile() {
|
|
||||||
this->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t CFile::open(const std::string &filepath, eOpenTypes mode) {
|
|
||||||
this->close();
|
|
||||||
int32_t openMode = 0;
|
|
||||||
|
|
||||||
// This depend on the devoptab implementation.
|
|
||||||
// see https://github.com/devkitPro/wut/blob/master/libraries/wutdevoptab/devoptab_fs_open.c#L21 fpr reference
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
default:
|
|
||||||
case ReadOnly: // file must exist
|
|
||||||
openMode = O_RDONLY;
|
|
||||||
break;
|
|
||||||
case WriteOnly: // file will be created / zerod
|
|
||||||
openMode = O_TRUNC | O_CREAT | O_WRONLY;
|
|
||||||
break;
|
|
||||||
case ReadWrite: // file must exist
|
|
||||||
openMode = O_RDWR;
|
|
||||||
break;
|
|
||||||
case Append: // append to file, file will be created if missing. write only
|
|
||||||
openMode = O_CREAT | O_APPEND | O_WRONLY;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Using fopen works only on the first launch as expected
|
|
||||||
//! on the second launch it causes issues because we don't overwrite
|
|
||||||
//! the .data sections which is needed for a normal application to re-init
|
|
||||||
//! this will be added with launching as RPX
|
|
||||||
iFd = ::open(filepath.c_str(), openMode);
|
|
||||||
if (iFd < 0)
|
|
||||||
return iFd;
|
|
||||||
|
|
||||||
|
|
||||||
filesize = ::lseek(iFd, 0, SEEK_END);
|
|
||||||
::lseek(iFd, 0, SEEK_SET);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t CFile::open(const uint8_t *mem, int32_t size) {
|
|
||||||
this->close();
|
|
||||||
|
|
||||||
mem_file = mem;
|
|
||||||
filesize = size;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CFile::close() {
|
|
||||||
if (iFd >= 0)
|
|
||||||
::close(iFd);
|
|
||||||
|
|
||||||
iFd = -1;
|
|
||||||
mem_file = NULL;
|
|
||||||
filesize = 0;
|
|
||||||
pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t CFile::read(uint8_t *ptr, size_t size) {
|
|
||||||
if (iFd >= 0) {
|
|
||||||
int32_t ret = ::read(iFd, ptr, size);
|
|
||||||
if (ret > 0)
|
|
||||||
pos += ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t readsize = size;
|
|
||||||
|
|
||||||
if (readsize > (int64_t) (filesize - pos))
|
|
||||||
readsize = filesize - pos;
|
|
||||||
|
|
||||||
if (readsize <= 0)
|
|
||||||
return readsize;
|
|
||||||
|
|
||||||
if (mem_file != NULL) {
|
|
||||||
memcpy(ptr, mem_file + pos, readsize);
|
|
||||||
pos += readsize;
|
|
||||||
return readsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t CFile::write(const uint8_t *ptr, size_t size) {
|
|
||||||
if (iFd >= 0) {
|
|
||||||
size_t done = 0;
|
|
||||||
while (done < size) {
|
|
||||||
int32_t ret = ::write(iFd, ptr, size - done);
|
|
||||||
if (ret <= 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ptr += ret;
|
|
||||||
done += ret;
|
|
||||||
pos += ret;
|
|
||||||
}
|
|
||||||
return done;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t CFile::seek(long int offset, int32_t origin) {
|
|
||||||
int32_t ret = 0;
|
|
||||||
int64_t newPos = pos;
|
|
||||||
|
|
||||||
if (origin == SEEK_SET) {
|
|
||||||
newPos = offset;
|
|
||||||
} else if (origin == SEEK_CUR) {
|
|
||||||
newPos += offset;
|
|
||||||
} else if (origin == SEEK_END) {
|
|
||||||
newPos = filesize + offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newPos < 0) {
|
|
||||||
pos = 0;
|
|
||||||
} else {
|
|
||||||
pos = newPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iFd >= 0)
|
|
||||||
ret = ::lseek(iFd, pos, SEEK_SET);
|
|
||||||
|
|
||||||
if (mem_file != NULL) {
|
|
||||||
if (pos > filesize) {
|
|
||||||
pos = filesize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t CFile::fwrite(const char *format, ...) {
|
|
||||||
char tmp[512];
|
|
||||||
tmp[0] = 0;
|
|
||||||
int32_t result = -1;
|
|
||||||
|
|
||||||
va_list va;
|
|
||||||
va_start(va, format);
|
|
||||||
if ((vsprintf(tmp, format, va) >= 0)) {
|
|
||||||
result = this->write((uint8_t *) tmp, strlen(tmp));
|
|
||||||
}
|
|
||||||
va_end(va);
|
|
||||||
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
#ifndef CFILE_HPP_
|
|
||||||
#define CFILE_HPP_
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <string>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <wut_types.h>
|
|
||||||
|
|
||||||
class CFile {
|
|
||||||
public:
|
|
||||||
enum eOpenTypes {
|
|
||||||
ReadOnly,
|
|
||||||
WriteOnly,
|
|
||||||
ReadWrite,
|
|
||||||
Append
|
|
||||||
};
|
|
||||||
|
|
||||||
CFile();
|
|
||||||
|
|
||||||
CFile(const std::string &filepath, eOpenTypes mode);
|
|
||||||
|
|
||||||
CFile(const uint8_t *memory, int32_t memsize);
|
|
||||||
|
|
||||||
virtual ~CFile();
|
|
||||||
|
|
||||||
int32_t open(const std::string &filepath, eOpenTypes mode);
|
|
||||||
|
|
||||||
int32_t open(const uint8_t *memory, int32_t memsize);
|
|
||||||
|
|
||||||
BOOL isOpen() const {
|
|
||||||
if (iFd >= 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (mem_file)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void close();
|
|
||||||
|
|
||||||
int32_t read(uint8_t *ptr, size_t size);
|
|
||||||
|
|
||||||
int32_t write(const uint8_t *ptr, size_t size);
|
|
||||||
|
|
||||||
int32_t fwrite(const char *format, ...);
|
|
||||||
|
|
||||||
int32_t seek(long int offset, int32_t origin);
|
|
||||||
|
|
||||||
uint64_t tell() {
|
|
||||||
return pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
uint64_t size() {
|
|
||||||
return filesize;
|
|
||||||
};
|
|
||||||
|
|
||||||
void rewind() {
|
|
||||||
this->seek(0, SEEK_SET);
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int32_t iFd;
|
|
||||||
const uint8_t *mem_file{};
|
|
||||||
uint64_t filesize{};
|
|
||||||
uint64_t pos{};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,127 +0,0 @@
|
|||||||
#include "FSUtils.h"
|
|
||||||
#include "CFile.hpp"
|
|
||||||
#include "logger.h"
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <malloc.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
|
|
||||||
int32_t FSUtils::CheckFile(const char *filepath) {
|
|
||||||
if (!filepath)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
struct stat filestat {};
|
|
||||||
|
|
||||||
char dirnoslash[strlen(filepath) + 2];
|
|
||||||
snprintf(dirnoslash, sizeof(dirnoslash), "%s", filepath);
|
|
||||||
|
|
||||||
while (dirnoslash[strlen(dirnoslash) - 1] == '/')
|
|
||||||
dirnoslash[strlen(dirnoslash) - 1] = '\0';
|
|
||||||
|
|
||||||
char *notRoot = strrchr(dirnoslash, '/');
|
|
||||||
if (!notRoot) {
|
|
||||||
strcat(dirnoslash, "/");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stat(dirnoslash, &filestat) == 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t FSUtils::CreateSubfolder(const char *fullpath) {
|
|
||||||
if (!fullpath)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
int32_t result = 0;
|
|
||||||
|
|
||||||
char dirnoslash[strlen(fullpath) + 1];
|
|
||||||
strcpy(dirnoslash, fullpath);
|
|
||||||
|
|
||||||
int32_t pos = strlen(dirnoslash) - 1;
|
|
||||||
while (dirnoslash[pos] == '/') {
|
|
||||||
dirnoslash[pos] = '\0';
|
|
||||||
pos--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CheckFile(dirnoslash)) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
char parentpath[strlen(dirnoslash) + 2];
|
|
||||||
strcpy(parentpath, dirnoslash);
|
|
||||||
char *ptr = strrchr(parentpath, '/');
|
|
||||||
|
|
||||||
if (!ptr) {
|
|
||||||
//!Device root directory (must be with '/')
|
|
||||||
strcat(parentpath, "/");
|
|
||||||
struct stat filestat;
|
|
||||||
if (stat(parentpath, &filestat) == 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr++;
|
|
||||||
ptr[0] = '\0';
|
|
||||||
|
|
||||||
result = CreateSubfolder(parentpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (mkdir(dirnoslash, 0777) == -1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t FSUtils::saveBufferToFile(const char *path, void *buffer, uint32_t size) {
|
|
||||||
CFile file(path, CFile::WriteOnly);
|
|
||||||
if (!file.isOpen()) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to open %s\n", path);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int32_t written = file.write((const uint8_t *) buffer, size);
|
|
||||||
file.close();
|
|
||||||
return written;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FSUtils::copyFile(const std::string &in, const std::string &out) {
|
|
||||||
// Using C++ buffers is **really** slow. Copying in 1023 byte chunks.
|
|
||||||
// Let's do it the old way.
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
int source = open(in.c_str(), O_RDONLY, 0);
|
|
||||||
if (source < 0) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to open source %s", in.c_str());
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int dest = open(out.c_str(), 0x602, 0644);
|
|
||||||
if (dest < 0) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to open dest %s", out.c_str());
|
|
||||||
close(source);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto bufferSize = 128 * 1024;
|
|
||||||
char *buf = (char *) malloc(bufferSize);
|
|
||||||
if (buf == nullptr) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to alloc buffer");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((size = read(source, buf, bufferSize)) > 0) {
|
|
||||||
write(dest, buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
|
|
||||||
close(source);
|
|
||||||
close(dest);
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <wut_types.h>
|
|
||||||
|
|
||||||
class FSUtils {
|
|
||||||
public:
|
|
||||||
//! todo: C++ class
|
|
||||||
static int32_t CreateSubfolder(const char *fullpath);
|
|
||||||
|
|
||||||
static int32_t CheckFile(const char *filepath);
|
|
||||||
|
|
||||||
static int32_t saveBufferToFile(const char *path, void *buffer, uint32_t size);
|
|
||||||
|
|
||||||
static bool copyFile(const std::string &in, const std::string &out);
|
|
||||||
};
|
|
@ -1,88 +1,52 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
bool gActivateUStealth = ACTIVATE_USTEALTH_DEFAULT;
|
bool gActivateUStealth = false;
|
||||||
bool gSkip4SecondOffStatusCheck = SKIP_4_SECOND_OFF_STATUS_CHECK_DEFAULT;
|
bool gSkip4SecondOffStatusCheck = true;
|
||||||
bool gConfigMenuHintShown = CONFIG_MENU_HINT_SHOWN_DEFAULT;
|
bool gConfigMenuHintShown = false;
|
||||||
bool gUpdateChecked = UPDATE_CHECKED_DEFAULT;
|
bool gUpdateChecked = false;
|
||||||
bool gForceNDMSuspendSuccess = FORCE_NDM_SUSPEND_SUCCESS_DEFAULT;
|
bool gForceNDMSuspendSuccess = true;
|
||||||
bool gAllowErrorNotifications = ALLOW_ERROR_NOTIFICATIONS_DEFAULT;
|
bool gAllowErrorNotifications = true;
|
||||||
std::string gLastHash = LAST_UPDATE_HASH_DEFAULT;
|
std::string gLastHash = {};
|
||||||
|
|
||||||
void boolItemChangedConfig(ConfigItemBoolean *item, bool newValue) {
|
void boolItemChangedConfig(ConfigItemBoolean *item, bool newValue) {
|
||||||
WUPSStorageError storageError;
|
wups_storage_item_t *cat_config;
|
||||||
auto subItemConfig = WUPSStorageAPI::GetSubItem(CAT_CONFIG, storageError);
|
if (WUPS_GetSubItem(nullptr, CAT_CONFIG, &cat_config) == WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
if (!subItemConfig) {
|
PROCESS_BOOL_ITEM_CHANGED(cat_config, USTEALTH_CONFIG_ID, gActivateUStealth);
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get sub item \"%s\": %s", CAT_CONFIG, WUPSStorageAPI::GetStatusStr(storageError).data());
|
PROCESS_BOOL_ITEM_CHANGED(cat_config, POWEROFFWARNING_CONFIG_ID, gSkip4SecondOffStatusCheck);
|
||||||
return;
|
PROCESS_BOOL_ITEM_CHANGED(cat_config, FORCE_NDM_SUSPEND_SUCCESS_CONFIG_ID, gForceNDMSuspendSuccess);
|
||||||
}
|
PROCESS_BOOL_ITEM_CHANGED(cat_config, ALLOW_ERROR_NOTIFICATIONS, gAllowErrorNotifications);
|
||||||
if (std::string_view(USTEALTH_CONFIG_ID) == item->identifier) {
|
|
||||||
gActivateUStealth = newValue;
|
|
||||||
storageError = subItemConfig->Store(USTEALTH_CONFIG_ID, newValue);
|
|
||||||
} else if (std::string_view(POWEROFFWARNING_CONFIG_ID) == item->identifier) {
|
|
||||||
gSkip4SecondOffStatusCheck = newValue;
|
|
||||||
storageError = subItemConfig->Store(POWEROFFWARNING_CONFIG_ID, newValue);
|
|
||||||
} else if (std::string_view(ALLOW_ERROR_NOTIFICATIONS) == item->identifier) {
|
|
||||||
gAllowErrorNotifications = newValue;
|
|
||||||
storageError = subItemConfig->Store(ALLOW_ERROR_NOTIFICATIONS, newValue);
|
|
||||||
} else if (std::string_view(FORCE_NDM_SUSPEND_SUCCESS_CONFIG_ID) == item->identifier) {
|
|
||||||
gForceNDMSuspendSuccess = newValue;
|
|
||||||
storageError = subItemConfig->Store(FORCE_NDM_SUSPEND_SUCCESS_CONFIG_ID, newValue);
|
|
||||||
} else {
|
} else {
|
||||||
return;
|
DEBUG_FUNCTION_LINE_ERR("Failed to get sub item: %s", CAT_CONFIG);
|
||||||
}
|
|
||||||
if (storageError != WUPS_STORAGE_ERROR_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to store %s. New value was %d", item->identifier, newValue);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WUPSConfigAPICallbackStatus ConfigMenuOpenedCallback(WUPSConfigCategoryHandle rootHandle) {
|
WUPS_GET_CONFIG() {
|
||||||
try {
|
// We open the storage, so we can persist the configuration the user did.
|
||||||
WUPSConfigCategory root = WUPSConfigCategory(rootHandle);
|
if (WUPS_OpenStorage() != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
|
DEBUG_FUNCTION_LINE("Failed to open storage");
|
||||||
auto menuPatches = WUPSConfigCategory::Create("Wii U Menu patches");
|
return 0;
|
||||||
|
|
||||||
menuPatches.add(WUPSConfigItemBoolean::Create(USTEALTH_CONFIG_ID,
|
|
||||||
"Avoid \"Format\" dialog on Wii U Menu",
|
|
||||||
ACTIVATE_USTEALTH_DEFAULT, gActivateUStealth,
|
|
||||||
&boolItemChangedConfig));
|
|
||||||
|
|
||||||
menuPatches.add(WUPSConfigItemBoolean::Create(POWEROFFWARNING_CONFIG_ID,
|
|
||||||
"Skip \"Shutdown warning\" on boot",
|
|
||||||
SKIP_4_SECOND_OFF_STATUS_CHECK_DEFAULT, gSkip4SecondOffStatusCheck,
|
|
||||||
&boolItemChangedConfig));
|
|
||||||
|
|
||||||
root.add(std::move(menuPatches));
|
|
||||||
|
|
||||||
auto otherPatches = WUPSConfigCategory::Create("Other patches");
|
|
||||||
|
|
||||||
otherPatches.add(WUPSConfigItemBoolean::Create(ALLOW_ERROR_NOTIFICATIONS,
|
|
||||||
"Allow error notifications",
|
|
||||||
ALLOW_ERROR_NOTIFICATIONS_DEFAULT, gAllowErrorNotifications,
|
|
||||||
&boolItemChangedConfig));
|
|
||||||
|
|
||||||
otherPatches.add(WUPSConfigItemBoolean::Create(FORCE_NDM_SUSPEND_SUCCESS_CONFIG_ID,
|
|
||||||
"Fix connecting to a 3DS in Mii Maker",
|
|
||||||
FORCE_NDM_SUSPEND_SUCCESS_DEFAULT, gForceNDMSuspendSuccess,
|
|
||||||
&boolItemChangedConfig));
|
|
||||||
root.add(std::move(otherPatches));
|
|
||||||
|
|
||||||
} catch (std::exception &e) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Exception: %s\n", e.what());
|
|
||||||
return WUPSCONFIG_API_CALLBACK_RESULT_ERROR;
|
|
||||||
}
|
}
|
||||||
return WUPSCONFIG_API_CALLBACK_RESULT_SUCCESS;
|
|
||||||
|
WUPSConfigHandle config;
|
||||||
|
WUPSConfig_CreateHandled(&config, "Aroma Base Plugin");
|
||||||
|
|
||||||
|
WUPSConfigCategoryHandle cat;
|
||||||
|
WUPSConfig_AddCategoryByNameHandled(config, "Wii U Menu patches", &cat);
|
||||||
|
WUPSConfigCategoryHandle catOther;
|
||||||
|
WUPSConfig_AddCategoryByNameHandled(config, "Other patches", &catOther);
|
||||||
|
|
||||||
|
WUPSConfigItemBoolean_AddToCategoryHandled(config, cat, USTEALTH_CONFIG_ID, "Avoid \"Format\" dialog on Wii U Menu", gActivateUStealth, &boolItemChangedConfig);
|
||||||
|
WUPSConfigItemBoolean_AddToCategoryHandled(config, cat, POWEROFFWARNING_CONFIG_ID, "Skip \"Shutdown warning\" on boot", gSkip4SecondOffStatusCheck, &boolItemChangedConfig);
|
||||||
|
|
||||||
|
WUPSConfigItemBoolean_AddToCategoryHandled(config, catOther, ALLOW_ERROR_NOTIFICATIONS, "Allow error notifications", gAllowErrorNotifications, &boolItemChangedConfig);
|
||||||
|
WUPSConfigItemBoolean_AddToCategoryHandled(config, catOther, FORCE_NDM_SUSPEND_SUCCESS_CONFIG_ID, "Fix connecting to a 3DS in Mii Maker", gForceNDMSuspendSuccess, &boolItemChangedConfig);
|
||||||
|
|
||||||
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigMenuClosedCallback() {
|
WUPS_CONFIG_CLOSED() {
|
||||||
WUPSStorageError storageError;
|
// Save all changes
|
||||||
if ((storageError = WUPSStorageAPI::SaveStorage()) != WUPS_STORAGE_ERROR_SUCCESS) {
|
if (WUPS_CloseStorage() != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to save storage: %d %s", storageError, WUPSStorageAPI_GetStatusStr(storageError));
|
DEBUG_FUNCTION_LINE_ERR("Failed to close storage");
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InitConfigMenu() {
|
|
||||||
WUPSConfigAPIOptionsV1 configOptions = {.name = "Aroma Base Plugin"};
|
|
||||||
if (WUPSConfigAPI_Init(configOptions, ConfigMenuOpenedCallback, ConfigMenuClosedCallback) != WUPSCONFIG_API_RESULT_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to init config api");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,23 +4,46 @@
|
|||||||
#include <wups/config/WUPSConfigItemBoolean.h>
|
#include <wups/config/WUPSConfigItemBoolean.h>
|
||||||
#include <wups/storage.h>
|
#include <wups/storage.h>
|
||||||
|
|
||||||
#define CAT_CONFIG "config"
|
#define CAT_CONFIG "config"
|
||||||
#define CAT_OTHER "other"
|
#define CAT_OTHER "other"
|
||||||
|
|
||||||
#define USTEALTH_CONFIG_ID "ustealth"
|
#define USTEALTH_CONFIG_ID "ustealth"
|
||||||
#define POWEROFFWARNING_CONFIG_ID "SkipPowerOffWarning"
|
#define POWEROFFWARNING_CONFIG_ID "SkipPowerOffWarning"
|
||||||
#define FORCE_NDM_SUSPEND_SUCCESS_CONFIG_ID "forceNDMSuspendSuccess"
|
#define FORCE_NDM_SUSPEND_SUCCESS_CONFIG_ID "forceNDMSuspendSuccess"
|
||||||
#define ALLOW_ERROR_NOTIFICATIONS "allowErrorNotifications"
|
#define ALLOW_ERROR_NOTIFICATIONS "allowErrorNotifications"
|
||||||
#define CONFIG_MENU_HINT_SHOWN_ID "configMenuHintShown"
|
|
||||||
#define LAST_UPDATE_HASH_ID "lastUpdateHash"
|
|
||||||
|
|
||||||
#define ACTIVATE_USTEALTH_DEFAULT false
|
|
||||||
#define SKIP_4_SECOND_OFF_STATUS_CHECK_DEFAULT true
|
#define CONFIG_MENU_HINT_SHOWN_ID "configMenuHintShown"
|
||||||
#define CONFIG_MENU_HINT_SHOWN_DEFAULT false
|
#define LAST_UPDATE_HASH_ID "lastUpdateHash"
|
||||||
#define UPDATE_CHECKED_DEFAULT false
|
|
||||||
#define FORCE_NDM_SUSPEND_SUCCESS_DEFAULT true
|
#define LOAD_BOOL_FROM_STORAGE(__cat, config_name, __variable__) \
|
||||||
#define ALLOW_ERROR_NOTIFICATIONS_DEFAULT true
|
if ((storageRes = WUPS_GetBool(__cat, config_name, &__variable__)) == WUPS_STORAGE_ERROR_NOT_FOUND) { \
|
||||||
#define LAST_UPDATE_HASH_DEFAULT std::string()
|
if (WUPS_StoreBool(__cat, config_name, __variable__) != WUPS_STORAGE_ERROR_SUCCESS) { \
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("Failed to store bool %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes); \
|
||||||
|
} \
|
||||||
|
} else if (storageRes != WUPS_STORAGE_ERROR_SUCCESS) { \
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("Failed to get bool %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
#define LOAD_STRING_FROM_STORAGE(__cat, config_name, __string, __string_length) \
|
||||||
|
if ((storageRes = WUPS_GetString(__cat, config_name, __string, __string_length)) == WUPS_STORAGE_ERROR_NOT_FOUND) { \
|
||||||
|
if (WUPS_StoreString(__cat, config_name, __string) != WUPS_STORAGE_ERROR_SUCCESS) { \
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("Failed to store string %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes); \
|
||||||
|
} \
|
||||||
|
} else if (storageRes != WUPS_STORAGE_ERROR_SUCCESS) { \
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("Failed to get bool %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
#define PROCESS_BOOL_ITEM_CHANGED(cat, __config__name, __variable__) \
|
||||||
|
if (std::string_view(item->configId) == __config__name) { \
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("New value in %s: %d", __config__name, newValue); \
|
||||||
|
__variable__ = newValue; \
|
||||||
|
WUPS_StoreInt(cat, __config__name, __variable__); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
extern bool gActivateUStealth;
|
extern bool gActivateUStealth;
|
||||||
extern bool gSkip4SecondOffStatusCheck;
|
extern bool gSkip4SecondOffStatusCheck;
|
||||||
@ -29,5 +52,3 @@ extern std::string gLastHash;
|
|||||||
extern bool gUpdateChecked;
|
extern bool gUpdateChecked;
|
||||||
extern bool gForceNDMSuspendSuccess;
|
extern bool gForceNDMSuspendSuccess;
|
||||||
extern bool gAllowErrorNotifications;
|
extern bool gAllowErrorNotifications;
|
||||||
|
|
||||||
void InitConfigMenu();
|
|
@ -1,122 +0,0 @@
|
|||||||
#include "utils.h"
|
|
||||||
#include "FSUtils.h"
|
|
||||||
#include "common.h"
|
|
||||||
#include "logger.h"
|
|
||||||
#include <coreinit/mcp.h>
|
|
||||||
#include <mocha/mocha.h>
|
|
||||||
#include <string>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
bool Utils::GetSerialId(std::string &serialID) {
|
|
||||||
bool result = false;
|
|
||||||
alignas(0x40) MCPSysProdSettings settings{};
|
|
||||||
auto handle = MCP_Open();
|
|
||||||
if (handle >= 0) {
|
|
||||||
if (MCP_GetSysProdSettings(handle, &settings) == 0) {
|
|
||||||
serialID = std::string(settings.code_id) + settings.serial_id;
|
|
||||||
result = true;
|
|
||||||
} else {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("Failed to get SerialId");
|
|
||||||
}
|
|
||||||
MCP_Close(handle);
|
|
||||||
} else {
|
|
||||||
DEBUG_FUNCTION_LINE_ERR("MCP_Open failed");
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool existsAsFile(std::string_view path) {
|
|
||||||
struct stat st {};
|
|
||||||
if (stat(path.data(), &st) >= 0 && S_ISREG(st.st_mode)) {
|
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("\"%s\" exists", path.data());
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("\"%s\" doesn't exists", path.data());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Migrates wiiu/apps/AromaUpdater.wuhb to wiiu/apps/AromaUpdater/AromaUpdater.wuhb
|
|
||||||
*/
|
|
||||||
void Utils::MigrateAromaUpdater() {
|
|
||||||
bool newExists = existsAsFile(AROMA_UPDATER_NEW_PATH_FULL);
|
|
||||||
bool oldExists = existsAsFile(AROMA_UPDATER_OLD_PATH_FULL);
|
|
||||||
|
|
||||||
if (newExists) {
|
|
||||||
if (oldExists) {
|
|
||||||
if (remove(AROMA_UPDATER_OLD_PATH_FULL) < 0) {
|
|
||||||
DEBUG_FUNCTION_LINE_WARN("Failed to remove old Aroma Updater: %d", errno);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("Only new AromaUpdater.wuhb exists");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else if (oldExists) {
|
|
||||||
if (!FSUtils::CreateSubfolder(AROMA_UPDATER_NEW_DIRECTORY_FULL)) {
|
|
||||||
DEBUG_FUNCTION_LINE_WARN("Failed to create \"%s\"", AROMA_UPDATER_NEW_DIRECTORY_FULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rename(AROMA_UPDATER_OLD_PATH_FULL, AROMA_UPDATER_NEW_PATH_FULL) < 0) {
|
|
||||||
DEBUG_FUNCTION_LINE_WARN("Failed to move Aroma Updater to new path");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("No AromaUpdater.wuhb exists");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dumps the OTP and SEEPROM when if it's no exists.
|
|
||||||
*/
|
|
||||||
void Utils::DumpOTPAndSeeprom() {
|
|
||||||
std::string serialId;
|
|
||||||
if (!Utils::GetSerialId(serialId)) {
|
|
||||||
DEBUG_FUNCTION_LINE_WARN("Failed to get SerialId of the console, skip OTP/SEEPROM dumping");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::string backupPathConsole = string_format(BACKUPS_DIRECTORY_FULL "/%s", serialId.c_str());
|
|
||||||
std::string backupPathConsoleOtpPath = backupPathConsole + "/otp.bin";
|
|
||||||
std::string backupPathConsoleSeepromPath = backupPathConsole + "/seeprom.bin";
|
|
||||||
|
|
||||||
if (!FSUtils::CreateSubfolder(backupPathConsole.c_str())) {
|
|
||||||
DEBUG_FUNCTION_LINE_WARN("Failed to create \"%s\"", backupPathConsole.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool seepromExists = FSUtils::CheckFile(backupPathConsoleSeepromPath.c_str());
|
|
||||||
bool otpExists = FSUtils::CheckFile(backupPathConsoleOtpPath.c_str());
|
|
||||||
|
|
||||||
if (!seepromExists) {
|
|
||||||
uint8_t data[0x200] = {};
|
|
||||||
if (Mocha_SEEPROMRead(data, 0, sizeof(data)) != sizeof(data)) {
|
|
||||||
DEBUG_FUNCTION_LINE_WARN("Failed to read SEEPROM");
|
|
||||||
} else {
|
|
||||||
if (FSUtils::saveBufferToFile(backupPathConsoleSeepromPath.c_str(), (void *) data, sizeof(data)) != sizeof(data)) {
|
|
||||||
DEBUG_FUNCTION_LINE_WARN("Failed to write SEEPROM backup (\"%s\")", backupPathConsoleSeepromPath.c_str());
|
|
||||||
} else {
|
|
||||||
DEBUG_FUNCTION_LINE_INFO("Created SEEPROM backup: \"%s\"", backupPathConsoleSeepromPath.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("SEEPROM backup already exists");
|
|
||||||
}
|
|
||||||
if (!otpExists) {
|
|
||||||
WiiUConsoleOTP otp = {};
|
|
||||||
if (Mocha_ReadOTP(&otp) != MOCHA_RESULT_SUCCESS) {
|
|
||||||
DEBUG_FUNCTION_LINE_WARN("Failed to read otp");
|
|
||||||
} else {
|
|
||||||
if (FSUtils::saveBufferToFile(backupPathConsoleOtpPath.c_str(), (void *) &otp, sizeof(otp)) != sizeof(otp)) {
|
|
||||||
DEBUG_FUNCTION_LINE_WARN("Failed to write otp backup (\"%s\")", backupPathConsoleOtpPath.c_str());
|
|
||||||
} else {
|
|
||||||
DEBUG_FUNCTION_LINE_INFO("Created OTP backup: \"%s\"", backupPathConsoleOtpPath.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DEBUG_FUNCTION_LINE_VERBOSE("OTP backup already exists");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove wrong file with typo
|
|
||||||
std::string backupPathConsoleOTPPathTypo = backupPathConsole + "/opt.bin";
|
|
||||||
if (FSUtils::CheckFile(backupPathConsoleOTPPathTypo.c_str())) {
|
|
||||||
remove(backupPathConsoleOTPPathTypo.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace Utils {
|
|
||||||
bool GetSerialId(std::string &serialID);
|
|
||||||
|
|
||||||
void MigrateAromaUpdater();
|
|
||||||
void DumpOTPAndSeeprom();
|
|
||||||
} // namespace Utils
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
std::string string_format(const std::string &format, Args... args) {
|
|
||||||
int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; // Extra space for '\0'
|
|
||||||
auto size = static_cast<size_t>(size_s);
|
|
||||||
auto buf = std::make_unique<char[]>(size);
|
|
||||||
std::snprintf(buf.get(), size, format.c_str(), args...);
|
|
||||||
return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user