Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WUPS 0.8.0 support #18

Merged
merged 8 commits into from
Apr 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ jobs:
clang-format:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: clang-format
run: |
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./src --exclude ./src/utils/json.hpp
build-binary:
runs-on: ubuntu-22.04
needs: clang-format
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: create version.h
run: |
git_hash=$(git rev-parse --short "$GITHUB_SHA")
Expand Down Expand Up @@ -48,7 +48,7 @@ jobs:
- name: zip artifact
run: zip -r ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip *.wps
- name: Create Release
uses: "softprops/action-gh-release@v1"
uses: "softprops/action-gh-release@v2"
with:
tag_name: ${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
draft: false
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ jobs:
clang-format:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: clang-format
run: |
docker run --rm -v ${PWD}:/src ghcr.io/wiiu-env/clang-format:13.0.0-2 -r ./src --exclude ./src/utils/json.hpp
build-binary:
runs-on: ubuntu-22.04
needs: clang-format
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: create version.h
run: |
git_hash=$(git rev-parse --short "${{ github.event.pull_request.head.sha }}")
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ sysapp.cbp
.idea/
cmake-build-debug/
CMakeLists.txt
*.zip
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
FROM ghcr.io/wiiu-env/devkitppc:20230621
FROM ghcr.io/wiiu-env/devkitppc:20240423

COPY --from=ghcr.io/wiiu-env/wiiupluginsystem:20230719 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/libnotifications:20230621 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/librpxloader:20230621 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/wiiupluginsystem:20240425 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/libnotifications:20240426 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/librpxloader:20240425 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/libcurlwrapper:20230715 /artifacts $DEVKITPRO
COPY --from=ghcr.io/wiiu-env/libsdutils:20230621 /artifacts $DEVKITPRO

Expand Down
33 changes: 24 additions & 9 deletions src/Hints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
#include <notifications/notification_defines.h>
#include <notifications/notifications.h>
#include <sdutils/sdutils.h>
#include <sys/fcntl.h>
#include <sys/unistd.h>
#include <thread>

std::unique_ptr<std::thread> sShowHintThread;
static bool sShutdownHintThread = false;

bool SaveHintShownToStorage(bool hintShown);

void ShowHints() {
bool isOverlayReady = false;
while (!sShutdownHintThread &&
Expand All @@ -29,7 +33,7 @@ void ShowHints() {
const char *tmp_file = "fs:/vol/external01/wiiu/write_lock";
int fd = -1;
if ((fd = open(tmp_file, O_CREAT | O_TRUNC | O_RDWR)) < 0) {
DEBUG_FUNCTION_LINE_VERBOSE("SD Card mounted but not writable");
DEBUG_FUNCTION_LINE_WARN("SD Card mounted but not writable. errno: %d", errno);
NotificationModuleStatus err;
NMColor red = {237, 28, 36, 255};
NotificationModuleHandle outHandle;
Expand All @@ -50,20 +54,31 @@ void ShowHints() {
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 &&
(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;
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();
}

gConfigMenuHintShown = true;
SaveHintShownToStorage(gConfigMenuHintShown);
} else {
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() {
sShowHintThread.reset();
sShutdownHintThread = false;
Expand Down
95 changes: 60 additions & 35 deletions src/UpdaterCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@
#include <padscore/wpad.h>
#include <rpxloader/rpxloader.h>
#include <string>
#include <sys/stat.h>
#include <thread>
#include <vpad/input.h>
#include <wups/function_patching.h>

static NotificationModuleHandle sAromaUpdateHandle = 0;
std::unique_ptr<std::thread> sCheckUpdateThread;
static bool sShutdownUpdateThread = false;
void UpdateCheckThreadEntry();

void ShowUpdateNotification();
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 sHoldForFramesTarget = 60;
Expand All @@ -41,6 +44,26 @@ 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() {
bool isOverlayReady = false;
while (!sShutdownUpdateThread &&
Expand All @@ -57,45 +80,46 @@ void UpdateCheckThreadEntry() {
std::string errorTextOut;
float progress;

if (DownloadUtils::DownloadFileToBuffer(AROMA_UPDATER_LAST_UPDATE_URL, outBuffer, responseCodeOut, errorOut, errorTextOut, &progress) == 0) {
try {
AromaUpdater::LatestVersion data = nlohmann::json::parse(outBuffer);
gUpdateChecked = true;
if (gLastHash.empty()) { // don't show update warning on first boot
gLastHash = data.getHash();
} 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 (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());
return;
}
try {
AromaUpdater::LatestVersion data = nlohmann::json::parse(outBuffer);
gUpdateChecked = true;

if (gLastHash.empty()) { // don't show update warning on first boot
gLastHash = data.getHash();
} else if (gLastHash != data.getHash()) {
ShowUpdateNotification();
} else if (gLastHash == data.getHash()) {
DEBUG_FUNCTION_LINE_VERBOSE("We don't need to update the hash");
return;
}

gLastHash = data.getHash();
} else {
DEBUG_FUNCTION_LINE_VERBOSE("We don't need to update the hash");
return;
}
// Update hash
gLastHash = data.getHash();

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");
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_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 {
DEBUG_FUNCTION_LINE_INFO("Download failed: %d %s", errorOut, errorTextOut.c_str());
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!");
}
}

Expand Down Expand Up @@ -158,6 +182,7 @@ DECL_FUNCTION(int32_t, VPADRead, VPADChan chan,

static uint32_t sWPADLastButtonHold[4] = {0, 0, 0, 0};
static uint32_t sHoldForXFramesWPAD[4] = {0, 0, 0, 0};

DECL_FUNCTION(void, WPADRead, WPADChan chan, WPADStatusProController *data) {
real_WPADRead(chan, data);
if (!sAromaUpdateHandle) {
Expand Down
92 changes: 52 additions & 40 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include <utils/logger.h>
#include <wups.h>

WUPS_PLUGIN_NAME("AromaBasePlugin");
WUPS_PLUGIN_NAME("Aroma Base Plugin");
WUPS_PLUGIN_DESCRIPTION("Implements small patches and checks for Aroma updates.");
WUPS_PLUGIN_VERSION(PLUGIN_VERSION_FULL);
WUPS_PLUGIN_AUTHOR("Maschell");
Expand All @@ -22,7 +22,54 @@ WUPS_PLUGIN_LICENSE("GPL");
WUPS_USE_WUT_DEVOPTAB();
WUPS_USE_STORAGE("aroma_base_plugin"); // Unique id for the storage api

static bool sSDUtilsInitDone = false;
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() {
initLogging();
Expand All @@ -36,45 +83,9 @@ INITIALIZE_PLUGIN() {
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;
}
InitConfigValuesFromStorage();

// 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);
}
InitConfigMenu();
}

ON_APPLICATION_START() {
Expand All @@ -92,6 +103,7 @@ ON_APPLICATION_START() {
ON_APPLICATION_ENDS() {
StopHintThread();
StopUpdaterCheckThread();
DownloadUtils::Deinit();
deinitLogging();
}

Expand Down
2 changes: 1 addition & 1 deletion src/main.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#pragma once
#include "version.h"

#define PLUGIN_VERSION "v0.1.3"
#define PLUGIN_VERSION "v0.1.4"
#define PLUGIN_VERSION_FULL PLUGIN_VERSION PLUGIN_VERSION_EXTRA
Loading