mirror of
https://github.com/wiiu-env/AromaBasePlugin.git
synced 2024-11-26 21:44:21 +01:00
First commit
This commit is contained in:
commit
2d49133dea
67
.clang-format
Normal file
67
.clang-format
Normal file
@ -0,0 +1,67 @@
|
||||
# Generated from CLion C/C++ Code Style settings
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: Consecutive
|
||||
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
|
||||
AlignOperands: Align
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Always
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
ColumnLimit: 0
|
||||
CompactNamespaces: false
|
||||
ContinuationIndentWidth: 8
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: All
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
59
.github/workflows/ci.yml
vendored
Normal file
59
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
name: CI-Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
clang-format:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: clang-format
|
||||
run: |
|
||||
docker run --rm -v ${PWD}:/src wiiuenv/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
|
||||
- name: create version.h
|
||||
run: |
|
||||
git_hash=$(git rev-parse --short "$GITHUB_SHA")
|
||||
cat <<EOF > ./src/version.h
|
||||
#pragma once
|
||||
#define PLUGIN_VERSION_EXTRA " (nightly-$git_hash)"
|
||||
EOF
|
||||
- name: build binary
|
||||
run: |
|
||||
docker build . -t builder
|
||||
docker run --rm -v ${PWD}:/project builder make
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: binary
|
||||
path: "*.wps"
|
||||
deploy-binary:
|
||||
needs: build-binary
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Get environment variables
|
||||
id: get_repository_name
|
||||
run: |
|
||||
echo REPOSITORY_NAME=$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $2}' | sed -e "s/:refs//") >> $GITHUB_ENV
|
||||
echo DATETIME=$(echo $(date '+%Y%m%d-%H%M%S')) >> $GITHUB_ENV
|
||||
- uses: actions/download-artifact@master
|
||||
with:
|
||||
name: binary
|
||||
- name: zip artifact
|
||||
run: zip -r ${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip *.wps
|
||||
- name: Create Release
|
||||
uses: "softprops/action-gh-release@v1"
|
||||
with:
|
||||
tag_name: ${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
|
||||
draft: false
|
||||
prerelease: true
|
||||
generate_release_notes: true
|
||||
name: Nightly-${{ env.REPOSITORY_NAME }}-${{ env.DATETIME }}
|
||||
files: |
|
||||
./${{ env.REPOSITORY_NAME }}_${{ env.DATETIME }}.zip
|
32
.github/workflows/pr.yml
vendored
Normal file
32
.github/workflows/pr.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
name: CI-PR
|
||||
|
||||
on: [ pull_request ]
|
||||
|
||||
jobs:
|
||||
clang-format:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: clang-format
|
||||
run: |
|
||||
docker run --rm -v ${PWD}:/src wiiuenv/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
|
||||
- name: create version.h
|
||||
run: |
|
||||
git_hash=$(git rev-parse --short "${{ github.event.pull_request.head.sha }}")
|
||||
cat <<EOF > ./src/version.h
|
||||
#pragma once
|
||||
#define PLUGIN_VERSION_EXTRA " (nightly-$git_hash)"
|
||||
EOF
|
||||
- name: build binary
|
||||
run: |
|
||||
docker build . -t builder
|
||||
docker run --rm -v ${PWD}:/project builder make
|
||||
- uses: actions/upload-artifact@master
|
||||
with:
|
||||
name: binary
|
||||
path: "*.wps"
|
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
build/*
|
||||
*.mod
|
||||
sysapp.layout
|
||||
sysapp.cbp
|
||||
*.elf
|
||||
*.wps
|
||||
.idea/
|
||||
cmake-build-debug/
|
||||
CMakeLists.txt
|
8
Dockerfile
Normal file
8
Dockerfile
Normal file
@ -0,0 +1,8 @@
|
||||
FROM wiiuenv/devkitppc:20221228
|
||||
|
||||
COPY --from=wiiuenv/wiiupluginsystem:20230126 /artifacts $DEVKITPRO
|
||||
COPY --from=wiiuenv/libnotifications:20230126 /artifacts $DEVKITPRO
|
||||
COPY --from=wiiuenv/librpxloader:20220903 /artifacts $DEVKITPRO
|
||||
COPY --from=wiiuenv/libcurlwrapper:20230121 /artifacts $DEVKITPRO
|
||||
|
||||
WORKDIR project
|
146
Makefile
Normal file
146
Makefile
Normal file
@ -0,0 +1,146 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
.SUFFIXES:
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
ifeq ($(strip $(DEVKITPRO)),)
|
||||
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
|
||||
endif
|
||||
|
||||
TOPDIR ?= $(CURDIR)
|
||||
|
||||
include $(DEVKITPRO)/wups/share/wups_rules
|
||||
|
||||
WUMS_ROOT := $(DEVKITPRO)/wums
|
||||
WUT_ROOT := $(DEVKITPRO)/wut
|
||||
#-------------------------------------------------------------------------------
|
||||
# TARGET is the name of the output
|
||||
# BUILD is the directory where object files & intermediate files will be placed
|
||||
# SOURCES is a list of directories containing source code
|
||||
# DATA is a list of directories containing data files
|
||||
# INCLUDES is a list of directories containing header files
|
||||
#-------------------------------------------------------------------------------
|
||||
TARGET := AromaBasePlugin
|
||||
BUILD := build
|
||||
SOURCES := src src/utils
|
||||
DATA := data
|
||||
INCLUDES := src
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# options for code generation
|
||||
#-------------------------------------------------------------------------------
|
||||
CFLAGS := -g -Wall -O2 -ffunction-sections \
|
||||
$(MACHDEP)
|
||||
|
||||
CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -D__WUPS__
|
||||
|
||||
CXXFLAGS := $(CFLAGS)
|
||||
|
||||
ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) $(WUPSSPECS)
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
CXXFLAGS += -DDEBUG -g
|
||||
CFLAGS += -DDEBUG -g
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG),VERBOSE)
|
||||
CXXFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
||||
CFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
||||
endif
|
||||
|
||||
LIBS := -lcurlwrapper -lnotifications -lrpxloader -lwups -lwut
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level
|
||||
# containing include and lib
|
||||
#-------------------------------------------------------------------------------
|
||||
LIBDIRS := $(PORTLIBS) $(WUPS_ROOT) $(WUMS_ROOT) $(WUT_ROOT)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
#-------------------------------------------------------------------------------
|
||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||
export TOPDIR := $(CURDIR)
|
||||
|
||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||
|
||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||
|
||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# use CXX for linking C++ projects, CC for standard C
|
||||
#-------------------------------------------------------------------------------
|
||||
ifeq ($(strip $(CPPFILES)),)
|
||||
#-------------------------------------------------------------------------------
|
||||
export LD := $(CC)
|
||||
#-------------------------------------------------------------------------------
|
||||
else
|
||||
#-------------------------------------------------------------------------------
|
||||
export LD := $(CXX)
|
||||
#-------------------------------------------------------------------------------
|
||||
endif
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||
|
||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||
-I$(CURDIR)/$(BUILD)
|
||||
|
||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||
|
||||
.PHONY: $(BUILD) clean all
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
all: $(BUILD)
|
||||
|
||||
$(BUILD):
|
||||
@$(shell [ ! -d $(BUILD) ] && mkdir -p $(BUILD))
|
||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
clean:
|
||||
@echo clean ...
|
||||
@rm -fr $(BUILD) $(TARGET).wps $(TARGET).elf
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
else
|
||||
.PHONY: all
|
||||
|
||||
DEPENDS := $(OFILES:.o=.d)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# main targets
|
||||
#-------------------------------------------------------------------------------
|
||||
all : $(OUTPUT).wps
|
||||
|
||||
$(OUTPUT).wps : $(OUTPUT).elf
|
||||
$(OUTPUT).elf : $(OFILES)
|
||||
|
||||
$(OFILES_SRC) : $(HFILES_BIN)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# you need a rule like this for each extension you use as binary data
|
||||
#-------------------------------------------------------------------------------
|
||||
%.bin.o %_bin.h : %.bin
|
||||
#-------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
@$(bin2o)
|
||||
|
||||
-include $(DEPENDS)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
endif
|
||||
#-------------------------------------------------------------------------------
|
50
README.md
Normal file
50
README.md
Normal file
@ -0,0 +1,50 @@
|
||||
# Aroma Base Plugin
|
||||
|
||||
Provides some simple patches for Wii U Menu and checks for Aroma updates.
|
||||
|
||||
## Installation
|
||||
|
||||
(`[ENVIRONMENT]` is a placeholder for the actual environment name.)
|
||||
|
||||
1. Copy the file `AromaBasePlugin.wps` into `sd:/wiiu/environments/[ENVIRONMENT]/plugins`.
|
||||
2. Requires the [WiiUPluginLoaderBackend](https://github.com/wiiu-env/WiiUPluginLoaderBackend) 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`.
|
||||
5. Requires the [RPXLoadingModule](https://github.com/wiiu-env/RPXLoadingModule) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
|
||||
|
||||
## Usage
|
||||
|
||||
Via the plugin config menu (press L, DPAD Down and Minus on the GamePad, Pro Controller or Classic Controller) you can configure the plugin. The available options are the following:
|
||||
- **Wii U Menu patches**:
|
||||
- Avoid "Format" dialog on Wii U Menu (UStealth): (Default is false)
|
||||
- Skips the "Format"-nag when launching the Wii U Menu with a non-formatted external drive.
|
||||
- Skip "Shutdown warning" on boot: (Default is true)
|
||||
- Hide the "Shutdown warning" after shutting the console down by pressing the power button for 4 seconds.
|
||||
|
||||
## Building
|
||||
|
||||
For building you need:
|
||||
- [wups](https://github.com/wiiu-env/WiiUPluginSystem)
|
||||
- [wut](https://github.com/decaf-emu/wut)
|
||||
- [libnotifications](https://github.com/wiiu-env/libnotifications)
|
||||
- [librpxloader](https://github.com/wiiu-env/librpxloader)
|
||||
- [libcurlwrapper](https://github.com/wiiu-env/libcurlwrapper)
|
||||
|
||||
## Building using the Dockerfile
|
||||
|
||||
It's possible to use a docker image for building. This way you don't need anything installed on your host system.
|
||||
|
||||
```
|
||||
# Build docker image (only needed once)
|
||||
docker build . -t aroma-base-plugin-builder
|
||||
|
||||
# make
|
||||
docker run -it --rm -v ${PWD}:/project aroma-base-plugin-builder make
|
||||
|
||||
# make clean
|
||||
docker run -it --rm -v ${PWD}:/project aroma-base-plugin-builder make clean
|
||||
```
|
||||
|
||||
## Format the code via docker
|
||||
|
||||
`docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./src --exclude ./src/utils/json.hpp -i`
|
55
src/Hints.cpp
Normal file
55
src/Hints.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "Hints.h"
|
||||
#include "utils/config.h"
|
||||
#include <coreinit/cache.h>
|
||||
#include <coreinit/thread.h>
|
||||
#include <notifications/notification_defines.h>
|
||||
#include <notifications/notifications.h>
|
||||
#include <thread>
|
||||
|
||||
std::unique_ptr<std::thread> sShowHintThread;
|
||||
static bool sShutdownHintThread = false;
|
||||
|
||||
void ShowHints() {
|
||||
bool isOverlayReady = false;
|
||||
while (!sShutdownHintThread &&
|
||||
NotificationModule_IsOverlayReady(&isOverlayReady) == NOTIFICATION_MODULE_RESULT_SUCCESS && !isOverlayReady) {
|
||||
OSSleepTicks(OSMillisecondsToTicks(16));
|
||||
}
|
||||
if (sShutdownHintThread || !isOverlayReady) {
|
||||
return;
|
||||
}
|
||||
if (!gConfigMenuHintShown) {
|
||||
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();
|
||||
}
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to show Notification: %d %s", err, NotificationModule_GetStatusStr(err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StartHintThread() {
|
||||
if (!gConfigMenuHintShown) {
|
||||
sShutdownHintThread = false;
|
||||
sShowHintThread = std::make_unique<std::thread>(ShowHints);
|
||||
} else {
|
||||
sShowHintThread.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void StopHintThread() {
|
||||
if (sShowHintThread != nullptr) {
|
||||
sShutdownHintThread = true;
|
||||
OSMemoryBarrier();
|
||||
sShowHintThread->join();
|
||||
sShowHintThread.reset();
|
||||
}
|
||||
}
|
5
src/Hints.h
Normal file
5
src/Hints.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
void StartHintThread();
|
||||
|
||||
void StopHintThread();
|
194
src/UpdaterCheck.cpp
Normal file
194
src/UpdaterCheck.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
#include "common.h"
|
||||
#include "utils/DownloadUtils.h"
|
||||
#include "utils/LatestVersion.h"
|
||||
#include "utils/config.h"
|
||||
#include "utils/input.h"
|
||||
#include <coreinit/cache.h>
|
||||
#include <coreinit/thread.h>
|
||||
#include <coreinit/time.h>
|
||||
#include <memory>
|
||||
#include <notifications/notifications.h>
|
||||
#include <padscore/wpad.h>
|
||||
#include <rpxloader/rpxloader.h>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vpad/input.h>
|
||||
|
||||
static NotificationModuleHandle sAromaUpdateHandle = 0;
|
||||
std::unique_ptr<std::thread> sCheckUpdateThread;
|
||||
static bool sShutdownUpdateThread = false;
|
||||
void UpdateCheckThreadEntry();
|
||||
|
||||
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;
|
||||
|
||||
void StartUpdaterCheckThread() {
|
||||
if (!gUpdateChecked && DownloadUtils::Init()) {
|
||||
sShutdownUpdateThread = false;
|
||||
sCheckUpdateThread = std::make_unique<std::thread>(UpdateCheckThreadEntry);
|
||||
} else {
|
||||
sCheckUpdateThread.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void StopUpdaterCheckThread() {
|
||||
if (sCheckUpdateThread != nullptr) {
|
||||
sShutdownUpdateThread = true;
|
||||
OSMemoryBarrier();
|
||||
sCheckUpdateThread->join();
|
||||
sCheckUpdateThread.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateCheckThreadEntry() {
|
||||
bool isOverlayReady = false;
|
||||
while (!sShutdownUpdateThread &&
|
||||
NotificationModule_IsOverlayReady(&isOverlayReady) == NOTIFICATION_MODULE_RESULT_SUCCESS && !isOverlayReady) {
|
||||
OSSleepTicks(OSMillisecondsToTicks(16));
|
||||
}
|
||||
if (sShutdownUpdateThread || !isOverlayReady) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string outBuffer;
|
||||
int responseCodeOut;
|
||||
int errorOut;
|
||||
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!");
|
||||
}
|
||||
|
||||
gLastHash = data.getHash();
|
||||
} else {
|
||||
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");
|
||||
}
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_INFO("Download failed: %d %s", errorOut, errorTextOut.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" uint32_t VPADGetButtonProcMode(uint32_t);
|
||||
|
||||
static bool updaterLaunched = false;
|
||||
static uint32_t sHoldForXFrames = 0;
|
||||
|
||||
bool CheckForButtonCombo(uint32_t trigger, uint32_t hold, uint32_t &holdForXFrames, uint32_t holdForFramesTarget) {
|
||||
if (trigger == HIDE_UPDATE_WARNING_VPAD_COMBO) {
|
||||
NotificationModule_FinishDynamicNotification(sAromaUpdateHandle, 0.0f);
|
||||
sAromaUpdateHandle = 0;
|
||||
return true;
|
||||
}
|
||||
if (hold == LAUNCH_AROMA_UPDATER_VPAD_COMBO) {
|
||||
if (++holdForXFrames > holdForFramesTarget) {
|
||||
RPXLoaderStatus err;
|
||||
if ((err = RPXLoader_LaunchHomebrew(AROMA_UPDATER_PATH)) == RPX_LOADER_RESULT_SUCCESS) {
|
||||
NotificationModule_FinishDynamicNotification(sAromaUpdateHandle, 2.0f);
|
||||
sAromaUpdateHandle = 0;
|
||||
updaterLaunched = true;
|
||||
return true;
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_ERR("RPXLoader_LaunchHomebrew failed: %s", RPXLoader_GetStatusStr(err));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
holdForXFrames = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DECL_FUNCTION(int32_t, VPADRead, VPADChan chan,
|
||||
VPADStatus *buffers,
|
||||
uint32_t count,
|
||||
VPADReadError *outError) {
|
||||
if (!sAromaUpdateHandle) {
|
||||
return real_VPADRead(chan, buffers, count, outError);
|
||||
}
|
||||
VPADReadError real_error;
|
||||
auto result = real_VPADRead(chan, buffers, count, &real_error);
|
||||
|
||||
if (!updaterLaunched && result > 0 && real_error == VPAD_READ_SUCCESS) {
|
||||
uint32_t end = 1;
|
||||
// Fix games like TP HD
|
||||
if (VPADGetButtonProcMode(chan) == 1) {
|
||||
end = result;
|
||||
}
|
||||
for (uint32_t i = 0; i < end; i++) {
|
||||
if (CheckForButtonCombo((buffers[i].trigger & 0x000FFFFF), (buffers[i].hold & 0x000FFFFF), sHoldForXFrames, sHoldForFramesTarget)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (outError) {
|
||||
*outError = real_error;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data && !updaterLaunched && chan >= 0 && chan < 4) {
|
||||
if (data[0].err == 0) {
|
||||
if (data[0].extensionType != 0xFF) {
|
||||
uint32_t curButtonHold = 0;
|
||||
if (data[0].extensionType == WPAD_EXT_CORE || data[0].extensionType == WPAD_EXT_NUNCHUK) {
|
||||
// button data is in the first 2 bytes for wiimotes
|
||||
curButtonHold = remapWiiMoteButtons(((uint16_t *) data)[0]);
|
||||
} else if (data[0].extensionType == WPAD_EXT_CLASSIC) {
|
||||
curButtonHold = remapClassicButtons(((uint32_t *) data)[10] & 0xFFFF);
|
||||
} else if (data[0].extensionType == WPAD_EXT_PRO_CONTROLLER) {
|
||||
curButtonHold = remapProButtons(data[0].buttons);
|
||||
}
|
||||
|
||||
uint32_t curButtonTrigger = (curButtonHold & (~(sWPADLastButtonHold[chan])));
|
||||
|
||||
if (CheckForButtonCombo(curButtonTrigger, curButtonHold, sHoldForXFramesWPAD[chan], sHoldForFramesTarget * 2)) {
|
||||
return;
|
||||
}
|
||||
|
||||
sWPADLastButtonHold[chan] = curButtonHold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We only want to patch Wii U Menu
|
||||
WUPS_MUST_REPLACE_FOR_PROCESS(VPADRead, WUPS_LOADER_LIBRARY_VPAD, VPADRead, WUPS_FP_TARGET_PROCESS_WII_U_MENU);
|
||||
WUPS_MUST_REPLACE_FOR_PROCESS(WPADRead, WUPS_LOADER_LIBRARY_PADSCORE, WPADRead, WUPS_FP_TARGET_PROCESS_WII_U_MENU);
|
4
src/UpdaterCheck.h
Normal file
4
src/UpdaterCheck.h
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
void StartUpdaterCheckThread();
|
||||
void StopUpdaterCheckThread();
|
5
src/common.h
Normal file
5
src/common.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
#define SD_CARD_PATH "fs:/vol/external01/"
|
||||
#define AROMA_UPDATER_PATH "wiiu/apps/AromaUpdater.wuhb"
|
||||
#define AROMA_UPDATER_PATH_FULL SD_CARD_PATH AROMA_UPDATER_PATH
|
||||
#define AROMA_UPDATER_LAST_UPDATE_URL "https://aroma.foryour.cafe/api/latest_version"
|
116
src/main.cpp
Normal file
116
src/main.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
#include "main.h"
|
||||
#include "Hints.h"
|
||||
#include "UpdaterCheck.h"
|
||||
#include "utils/DownloadUtils.h"
|
||||
#include "utils/LatestVersion.h"
|
||||
#include "utils/config.h"
|
||||
#include <coreinit/title.h>
|
||||
#include <malloc.h>
|
||||
#include <nn/spm.h>
|
||||
#include <notifications/notifications.h>
|
||||
#include <rpxloader/rpxloader.h>
|
||||
#include <utils/logger.h>
|
||||
#include <wups.h>
|
||||
|
||||
WUPS_PLUGIN_NAME("AromaBasePlugin");
|
||||
WUPS_PLUGIN_DESCRIPTION("Implements small patches and checks for Aroma updates.");
|
||||
WUPS_PLUGIN_VERSION(PLUGIN_VERSION_FULL);
|
||||
WUPS_PLUGIN_AUTHOR("Maschell");
|
||||
WUPS_PLUGIN_LICENSE("GPL");
|
||||
|
||||
WUPS_USE_WUT_DEVOPTAB();
|
||||
WUPS_USE_STORAGE("aroma_base_plugin"); // Unique id for the storage api
|
||||
|
||||
INITIALIZE_PLUGIN() {
|
||||
initLogging();
|
||||
if (NotificationModule_InitLibrary() != NOTIFICATION_MODULE_RESULT_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("NotificationModule_InitLibrary failed");
|
||||
}
|
||||
if (RPXLoader_InitLibrary() != RPX_LOADER_RESULT_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("RPXLoader_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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
ON_APPLICATION_START() {
|
||||
initLogging();
|
||||
uint64_t titleID = OSGetTitleID();
|
||||
if (titleID == 0x0005001010040000L || // Wii U Menu
|
||||
titleID == 0x0005001010040100L ||
|
||||
titleID == 0x0005001010040200L) {
|
||||
|
||||
StartHintThread();
|
||||
StartUpdaterCheckThread();
|
||||
}
|
||||
}
|
||||
|
||||
ON_APPLICATION_ENDS() {
|
||||
StopHintThread();
|
||||
StopUpdaterCheckThread();
|
||||
deinitLogging();
|
||||
}
|
||||
|
||||
DEINITIALIZE_PLUGIN() {
|
||||
NotificationModule_DeInitLibrary();
|
||||
RPXLoader_DeInitLibrary();
|
||||
}
|
||||
|
||||
DECL_FUNCTION(int32_t, IsStorageMaybePcFormatted, bool *isPcFormatted, nn::spm::StorageIndex *index) {
|
||||
// Make sure the index is valid
|
||||
int32_t res = real_IsStorageMaybePcFormatted(isPcFormatted, index);
|
||||
if (gActivateUStealth && res == 0) {
|
||||
// always return false which makes the Wii U menu stop nagging about this drive
|
||||
*isPcFormatted = false;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
DECL_FUNCTION(bool, MCP_Get4SecondOffStatus, int32_t handle) {
|
||||
if (gSkip4SecondOffStatusCheck) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return real_MCP_Get4SecondOffStatus(handle);
|
||||
}
|
||||
|
||||
// Only replace for the Wii U Menu
|
||||
WUPS_MUST_REPLACE_FOR_PROCESS(IsStorageMaybePcFormatted, WUPS_LOADER_LIBRARY_NN_SPM, IsStorageMaybePcFormatted__Q2_2nn3spmFPbQ3_2nn3spm12StorageIndex, WUPS_FP_TARGET_PROCESS_WII_U_MENU);
|
||||
WUPS_MUST_REPLACE_FOR_PROCESS(MCP_Get4SecondOffStatus, WUPS_LOADER_LIBRARY_COREINIT, MCP_Get4SecondOffStatus, WUPS_FP_TARGET_PROCESS_WII_U_MENU);
|
5
src/main.h
Normal file
5
src/main.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
#include "version.h"
|
||||
|
||||
#define PLUGIN_VERSION "v0.1"
|
||||
#define PLUGIN_VERSION_FULL PLUGIN_VERSION PLUGIN_VERSION_EXTRA
|
137
src/utils/DownloadUtils.cpp
Normal file
137
src/utils/DownloadUtils.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
#include "DownloadUtils.h"
|
||||
#include "logger.h"
|
||||
#include <coreinit/cache.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
#define IO_BUFSIZE (128 * 1024) // 128 KB
|
||||
|
||||
bool DownloadUtils::libInitDone = false;
|
||||
|
||||
static int initSocket(void *ptr, curl_socket_t socket, curlsocktype type) {
|
||||
int o = 1;
|
||||
|
||||
// Activate WinScale
|
||||
int r;
|
||||
if ((uint32_t) ptr != 0x13371337) {
|
||||
r = reinterpret_cast<decltype(&setsockopt)>(ptr)(socket, SOL_SOCKET, SO_WINSCALE, &o, sizeof(o));
|
||||
} else {
|
||||
r = setsockopt(socket, SOL_SOCKET, SO_WINSCALE, &o, sizeof(o));
|
||||
}
|
||||
if (r != 0) {
|
||||
DEBUG_FUNCTION_LINE_ERR("initSocket: Error setting WinScale: %d", r);
|
||||
return CURL_SOCKOPT_ERROR;
|
||||
}
|
||||
|
||||
o = IO_BUFSIZE;
|
||||
// Set receive buffersize
|
||||
if ((uint32_t) ptr != 0x13371337) {
|
||||
r = reinterpret_cast<decltype(&setsockopt)>(ptr)(socket, SOL_SOCKET, SO_RCVBUF, &o, sizeof(o));
|
||||
} else {
|
||||
r = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &o, sizeof(o));
|
||||
}
|
||||
if (r != 0) {
|
||||
DEBUG_FUNCTION_LINE_ERR("initSocket: Error setting RBS: %d", r);
|
||||
return CURL_SOCKOPT_ERROR;
|
||||
}
|
||||
|
||||
return CURL_SOCKOPT_OK;
|
||||
}
|
||||
|
||||
size_t writeCallback(char *buf, size_t size, size_t nmemb, void *up) {
|
||||
auto *data = (std::string *) up;
|
||||
data->append(buf, size * nmemb);
|
||||
return size * nmemb; //tell curl how many bytes we handled
|
||||
}
|
||||
|
||||
int progress_callback(void *clientp,
|
||||
curl_off_t dltotal,
|
||||
curl_off_t dlnow,
|
||||
curl_off_t ultotal,
|
||||
curl_off_t ulnow) {
|
||||
if (clientp != nullptr) {
|
||||
auto *progress = (float *) clientp;
|
||||
if (dltotal > 0 && dlnow > 0) {
|
||||
*progress = (float) dlnow / (float) dltotal;
|
||||
} else {
|
||||
*progress = 0.0f;
|
||||
}
|
||||
OSMemoryBarrier();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool DownloadUtils::Init() {
|
||||
if (libInitDone) {
|
||||
return true;
|
||||
}
|
||||
CURLcode res = curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
if (res != CURLE_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
libInitDone = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DownloadUtils::Deinit() {
|
||||
if (!libInitDone) {
|
||||
return;
|
||||
}
|
||||
|
||||
curl_global_cleanup();
|
||||
libInitDone = false;
|
||||
}
|
||||
|
||||
int DownloadUtils::DownloadFileToBuffer(const std::string &url, std::string &outBuffer, int &responseCodeOut, int &errorOut, std::string &errorTextOut, float *progress) {
|
||||
if (!libInitDone) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Start a curl session
|
||||
CURL *curl = curl_easy_init();
|
||||
if (!curl) {
|
||||
curl_global_cleanup();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Enable optimizations
|
||||
curl_easy_setopt(curl, CURLOPT_SOCKOPTDATA, 0x13371337);
|
||||
curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, initSocket);
|
||||
|
||||
// Follow redirects
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
|
||||
// Set the download URL
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
|
||||
if (progress != nullptr) {
|
||||
/* pass struct to callback */
|
||||
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, progress);
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
|
||||
}
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &outBuffer);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &writeCallback);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L);
|
||||
|
||||
char error[CURL_ERROR_SIZE]; /* needs to be at least this big */
|
||||
memset(error, 0, sizeof(error));
|
||||
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
|
||||
|
||||
errorTextOut = {};
|
||||
errorOut = 0;
|
||||
|
||||
responseCodeOut = -1;
|
||||
if ((errorOut = curl_easy_perform(curl)) != CURLE_OK) {
|
||||
errorTextOut = error;
|
||||
curl_easy_cleanup(curl);
|
||||
return -1;
|
||||
}
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCodeOut);
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
return 0;
|
||||
}
|
12
src/utils/DownloadUtils.h
Normal file
12
src/utils/DownloadUtils.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
class DownloadUtils {
|
||||
public:
|
||||
static bool Init();
|
||||
static void Deinit();
|
||||
|
||||
static int DownloadFileToBuffer(const std::string &url, std::string &outBuffer, int &responseCodeOut, int &errorOut, std::string &errorTextOut, float *progress);
|
||||
|
||||
static bool libInitDone;
|
||||
};
|
61
src/utils/LatestVersion.h
Normal file
61
src/utils/LatestVersion.h
Normal file
@ -0,0 +1,61 @@
|
||||
// To parse this JSON data, first install
|
||||
//
|
||||
// json.hpp https://github.com/nlohmann/json
|
||||
//
|
||||
// Then include this file, and then do
|
||||
//
|
||||
// LatestVersion data = nlohmann::json::parse(jsonString);
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "json.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <regex>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace AromaUpdater {
|
||||
using nlohmann::json;
|
||||
|
||||
#ifndef NLOHMANN_UNTYPED_AromaUpdater_HELPERHELPER
|
||||
#define NLOHMANN_UNTYPED_AromaUpdater_HELPERHELPER
|
||||
inline json get_untyped(const json &j, const char *property) {
|
||||
if (j.find(property) != j.end()) {
|
||||
return j.at(property).get<json>();
|
||||
}
|
||||
return json();
|
||||
}
|
||||
|
||||
inline json get_untyped(const json &j, std::string property) {
|
||||
return get_untyped(j, property.data());
|
||||
}
|
||||
#endif
|
||||
|
||||
class LatestVersion {
|
||||
public:
|
||||
LatestVersion() = default;
|
||||
virtual ~LatestVersion() = default;
|
||||
|
||||
private:
|
||||
std::string hash;
|
||||
std::string description;
|
||||
|
||||
public:
|
||||
const std::string &getHash() const { return hash; }
|
||||
std::string &getMutableHash() { return hash; }
|
||||
void setHash(const std::string &value) { this->hash = value; }
|
||||
|
||||
const std::string &getDescription() const { return description; }
|
||||
std::string &getMutableDescription() { return description; }
|
||||
void setDescription(const std::string &value) { this->description = value; }
|
||||
};
|
||||
} // namespace AromaUpdater
|
||||
|
||||
namespace AromaUpdater {
|
||||
void from_json(const json &j, LatestVersion &x);
|
||||
|
||||
inline void from_json(const json &j, LatestVersion &x) {
|
||||
x.setHash(j.at("hash").get<std::string>());
|
||||
x.setDescription(j.at("description").get<std::string>());
|
||||
}
|
||||
} // namespace AromaUpdater
|
43
src/utils/config.cpp
Normal file
43
src/utils/config.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include "config.h"
|
||||
|
||||
bool gActivateUStealth = false;
|
||||
bool gSkip4SecondOffStatusCheck = true;
|
||||
bool gConfigMenuHintShown = false;
|
||||
bool gUpdateChecked = false;
|
||||
std::string gLastHash = {};
|
||||
|
||||
void boolItemChangedConfig(ConfigItemBoolean *item, bool newValue) {
|
||||
wups_storage_item_t *cat_config;
|
||||
if (WUPS_GetSubItem(nullptr, CAT_CONFIG, &cat_config) == WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
PROCESS_BOOL_ITEM_CHANGED(cat_config, USTEALTH_CONFIG_ID, gActivateUStealth);
|
||||
PROCESS_BOOL_ITEM_CHANGED(cat_config, POWEROFFWARNING_CONFIG_ID, gSkip4SecondOffStatusCheck);
|
||||
} else {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to get sub item: %s", CAT_CONFIG);
|
||||
}
|
||||
}
|
||||
|
||||
WUPS_GET_CONFIG() {
|
||||
// We open the storage, so we can persist the configuration the user did.
|
||||
if (WUPS_OpenStorage() != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE("Failed to open storage");
|
||||
return 0;
|
||||
}
|
||||
|
||||
WUPSConfigHandle config;
|
||||
WUPSConfig_CreateHandled(&config, "Aroma Base Plugin");
|
||||
|
||||
WUPSConfigCategoryHandle cat;
|
||||
WUPSConfig_AddCategoryByNameHandled(config, "Wii U Menu patches", &cat);
|
||||
|
||||
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);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
WUPS_CONFIG_CLOSED() {
|
||||
// Save all changes
|
||||
if (WUPS_CloseStorage() != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||
DEBUG_FUNCTION_LINE_ERR("Failed to close storage");
|
||||
}
|
||||
}
|
51
src/utils/config.h
Normal file
51
src/utils/config.h
Normal file
@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
#include "logger.h"
|
||||
#include <string>
|
||||
#include <wups/config/WUPSConfigItemBoolean.h>
|
||||
#include <wups/storage.h>
|
||||
|
||||
|
||||
#define CAT_CONFIG "config"
|
||||
#define CAT_OTHER "other"
|
||||
|
||||
#define USTEALTH_CONFIG_ID "ustealth"
|
||||
#define POWEROFFWARNING_CONFIG_ID "SkipPowerOffWarning"
|
||||
|
||||
|
||||
#define CONFIG_MENU_HINT_SHOWN_ID "configMenuHintShown"
|
||||
#define LAST_UPDATE_HASH_ID "lastUpdateHash"
|
||||
|
||||
#define LOAD_BOOL_FROM_STORAGE(__cat, config_name, __variable__) \
|
||||
if ((storageRes = WUPS_GetBool(__cat, config_name, &__variable__)) == WUPS_STORAGE_ERROR_NOT_FOUND) { \
|
||||
if (WUPS_StoreBool(__cat, config_name, __variable__) != WUPS_STORAGE_ERROR_SUCCESS) { \
|
||||
DEBUG_FUNCTION_LINE_WARN("Failed to store bool"); \
|
||||
} \
|
||||
} 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"); \
|
||||
} \
|
||||
} 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 gSkip4SecondOffStatusCheck;
|
||||
extern bool gConfigMenuHintShown;
|
||||
extern std::string gLastHash;
|
||||
extern bool gUpdateChecked;
|
150
src/utils/input.cpp
Normal file
150
src/utils/input.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#include "input.h"
|
||||
|
||||
uint32_t remapWiiMoteButtons(uint32_t buttons) {
|
||||
uint32_t conv_buttons = 0;
|
||||
|
||||
if (buttons & WPAD_BUTTON_LEFT) {
|
||||
conv_buttons |= VPAD_BUTTON_LEFT;
|
||||
}
|
||||
|
||||
if (buttons & WPAD_BUTTON_RIGHT) {
|
||||
conv_buttons |= VPAD_BUTTON_RIGHT;
|
||||
}
|
||||
|
||||
if (buttons & WPAD_BUTTON_DOWN) {
|
||||
conv_buttons |= VPAD_BUTTON_DOWN;
|
||||
}
|
||||
|
||||
if (buttons & WPAD_BUTTON_UP) {
|
||||
conv_buttons |= VPAD_BUTTON_UP;
|
||||
}
|
||||
|
||||
if (buttons & WPAD_BUTTON_PLUS) {
|
||||
conv_buttons |= VPAD_BUTTON_PLUS;
|
||||
}
|
||||
|
||||
if (buttons & WPAD_BUTTON_B) {
|
||||
conv_buttons |= VPAD_BUTTON_B;
|
||||
}
|
||||
|
||||
if (buttons & WPAD_BUTTON_A) {
|
||||
conv_buttons |= VPAD_BUTTON_A;
|
||||
}
|
||||
|
||||
if (buttons & WPAD_BUTTON_MINUS) {
|
||||
conv_buttons |= VPAD_BUTTON_MINUS;
|
||||
}
|
||||
|
||||
if (buttons & WPAD_BUTTON_HOME) {
|
||||
conv_buttons |= VPAD_BUTTON_HOME;
|
||||
}
|
||||
return conv_buttons;
|
||||
}
|
||||
|
||||
uint32_t remapClassicButtons(uint32_t buttons) {
|
||||
uint32_t conv_buttons = 0;
|
||||
|
||||
if (buttons & WPAD_CLASSIC_BUTTON_LEFT) {
|
||||
conv_buttons |= VPAD_BUTTON_LEFT;
|
||||
}
|
||||
if (buttons & WPAD_CLASSIC_BUTTON_RIGHT) {
|
||||
conv_buttons |= VPAD_BUTTON_RIGHT;
|
||||
}
|
||||
if (buttons & WPAD_CLASSIC_BUTTON_DOWN) {
|
||||
conv_buttons |= VPAD_BUTTON_DOWN;
|
||||
}
|
||||
if (buttons & WPAD_CLASSIC_BUTTON_UP) {
|
||||
conv_buttons |= VPAD_BUTTON_UP;
|
||||
}
|
||||
if (buttons & WPAD_CLASSIC_BUTTON_PLUS) {
|
||||
conv_buttons |= VPAD_BUTTON_PLUS;
|
||||
}
|
||||
if (buttons & WPAD_CLASSIC_BUTTON_X) {
|
||||
conv_buttons |= VPAD_BUTTON_X;
|
||||
}
|
||||
if (buttons & WPAD_CLASSIC_BUTTON_Y) {
|
||||
conv_buttons |= VPAD_BUTTON_Y;
|
||||
}
|
||||
if (buttons & WPAD_CLASSIC_BUTTON_B) {
|
||||
conv_buttons |= VPAD_BUTTON_B;
|
||||
}
|
||||
if (buttons & WPAD_CLASSIC_BUTTON_A) {
|
||||
conv_buttons |= VPAD_BUTTON_A;
|
||||
}
|
||||
if (buttons & WPAD_CLASSIC_BUTTON_MINUS) {
|
||||
conv_buttons |= VPAD_BUTTON_MINUS;
|
||||
}
|
||||
if (buttons & WPAD_CLASSIC_BUTTON_HOME) {
|
||||
conv_buttons |= VPAD_BUTTON_HOME;
|
||||
}
|
||||
if (buttons & WPAD_CLASSIC_BUTTON_ZR) {
|
||||
conv_buttons |= VPAD_BUTTON_ZR;
|
||||
}
|
||||
if (buttons & WPAD_CLASSIC_BUTTON_ZL) {
|
||||
conv_buttons |= VPAD_BUTTON_ZL;
|
||||
}
|
||||
if (buttons & WPAD_CLASSIC_BUTTON_R) {
|
||||
conv_buttons |= VPAD_BUTTON_R;
|
||||
}
|
||||
if (buttons & WPAD_CLASSIC_BUTTON_L) {
|
||||
conv_buttons |= VPAD_BUTTON_L;
|
||||
}
|
||||
return conv_buttons;
|
||||
}
|
||||
|
||||
uint32_t remapProButtons(uint32_t buttons) {
|
||||
uint32_t conv_buttons = 0;
|
||||
|
||||
if (buttons & WPAD_PRO_BUTTON_LEFT) {
|
||||
conv_buttons |= VPAD_BUTTON_LEFT;
|
||||
}
|
||||
if (buttons & WPAD_PRO_BUTTON_RIGHT) {
|
||||
conv_buttons |= VPAD_BUTTON_RIGHT;
|
||||
}
|
||||
if (buttons & WPAD_PRO_BUTTON_DOWN) {
|
||||
conv_buttons |= VPAD_BUTTON_DOWN;
|
||||
}
|
||||
if (buttons & WPAD_PRO_BUTTON_UP) {
|
||||
conv_buttons |= VPAD_BUTTON_UP;
|
||||
}
|
||||
if (buttons & WPAD_PRO_BUTTON_PLUS) {
|
||||
conv_buttons |= VPAD_BUTTON_PLUS;
|
||||
}
|
||||
if (buttons & WPAD_PRO_BUTTON_X) {
|
||||
conv_buttons |= VPAD_BUTTON_X;
|
||||
}
|
||||
if (buttons & WPAD_PRO_BUTTON_Y) {
|
||||
conv_buttons |= VPAD_BUTTON_Y;
|
||||
}
|
||||
if (buttons & WPAD_PRO_BUTTON_B) {
|
||||
conv_buttons |= VPAD_BUTTON_B;
|
||||
}
|
||||
if (buttons & WPAD_PRO_BUTTON_A) {
|
||||
conv_buttons |= VPAD_BUTTON_A;
|
||||
}
|
||||
if (buttons & WPAD_PRO_BUTTON_MINUS) {
|
||||
conv_buttons |= VPAD_BUTTON_MINUS;
|
||||
}
|
||||
if (buttons & WPAD_PRO_BUTTON_HOME) {
|
||||
conv_buttons |= VPAD_BUTTON_HOME;
|
||||
}
|
||||
if (buttons & WPAD_PRO_TRIGGER_ZR) {
|
||||
conv_buttons |= VPAD_BUTTON_ZR;
|
||||
}
|
||||
if (buttons & WPAD_PRO_TRIGGER_ZL) {
|
||||
conv_buttons |= VPAD_BUTTON_ZL;
|
||||
}
|
||||
if (buttons & WPAD_PRO_TRIGGER_R) {
|
||||
conv_buttons |= VPAD_BUTTON_R;
|
||||
}
|
||||
if (buttons & WPAD_PRO_TRIGGER_L) {
|
||||
conv_buttons |= VPAD_BUTTON_L;
|
||||
}
|
||||
if (buttons & WPAD_PRO_BUTTON_STICK_L) {
|
||||
conv_buttons |= VPAD_BUTTON_STICK_L;
|
||||
}
|
||||
if (buttons & WPAD_PRO_BUTTON_STICK_R) {
|
||||
conv_buttons |= VPAD_BUTTON_STICK_R;
|
||||
}
|
||||
return conv_buttons;
|
||||
}
|
9
src/utils/input.h
Normal file
9
src/utils/input.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <padscore/kpad.h>
|
||||
#include <vpad/input.h>
|
||||
|
||||
uint32_t remapWiiMoteButtons(uint32_t buttons);
|
||||
uint32_t remapClassicButtons(uint32_t buttons);
|
||||
uint32_t remapProButtons(uint32_t buttons);
|
24642
src/utils/json.hpp
Normal file
24642
src/utils/json.hpp
Normal file
File diff suppressed because it is too large
Load Diff
178
src/utils/json_fwd.hpp
Normal file
178
src/utils/json_fwd.hpp
Normal file
@ -0,0 +1,178 @@
|
||||
/* clang-format off */
|
||||
|
||||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++
|
||||
// | | |__ | | | | | | version 3.11.2
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||
|
||||
#include <cstdint> // int64_t, uint64_t
|
||||
#include <map> // map
|
||||
#include <memory> // allocator
|
||||
#include <string> // string
|
||||
#include <vector> // vector
|
||||
|
||||
// #include <nlohmann/detail/abi_macros.hpp>
|
||||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++
|
||||
// | | |__ | | | | | | version 3.11.2
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
|
||||
|
||||
// This file contains all macro definitions affecting or depending on the ABI
|
||||
|
||||
#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
|
||||
#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
|
||||
#if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2
|
||||
#warning "Already included a different version of the library!"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
|
||||
#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
|
||||
#define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum)
|
||||
|
||||
#ifndef JSON_DIAGNOSTICS
|
||||
#define JSON_DIAGNOSTICS 0
|
||||
#endif
|
||||
|
||||
#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
|
||||
#endif
|
||||
|
||||
#if JSON_DIAGNOSTICS
|
||||
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
|
||||
#else
|
||||
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
|
||||
#endif
|
||||
|
||||
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
|
||||
#else
|
||||
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||
#endif
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
|
||||
#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
|
||||
#endif
|
||||
|
||||
// Construct the namespace ABI tags component
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
|
||||
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
|
||||
|
||||
#define NLOHMANN_JSON_ABI_TAGS \
|
||||
NLOHMANN_JSON_ABI_TAGS_CONCAT( \
|
||||
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
|
||||
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
|
||||
|
||||
// Construct the namespace version component
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
|
||||
_v ## major ## _ ## minor ## _ ## patch
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
|
||||
|
||||
#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION
|
||||
#else
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
|
||||
NLOHMANN_JSON_VERSION_MINOR, \
|
||||
NLOHMANN_JSON_VERSION_PATCH)
|
||||
#endif
|
||||
|
||||
// Combine namespace components
|
||||
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
|
||||
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
|
||||
NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE
|
||||
#define NLOHMANN_JSON_NAMESPACE \
|
||||
nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
|
||||
NLOHMANN_JSON_ABI_TAGS, \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION)
|
||||
#endif
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
|
||||
namespace nlohmann \
|
||||
{ \
|
||||
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
|
||||
NLOHMANN_JSON_ABI_TAGS, \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION) \
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE_END
|
||||
#define NLOHMANN_JSON_NAMESPACE_END \
|
||||
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
|
||||
} // namespace nlohmann
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
@brief namespace for Niels Lohmann
|
||||
@see https://github.com/nlohmann
|
||||
@since version 1.0.0
|
||||
*/
|
||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
|
||||
/*!
|
||||
@brief default JSONSerializer template argument
|
||||
|
||||
This serializer ignores the template arguments and uses ADL
|
||||
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
|
||||
for serialization.
|
||||
*/
|
||||
template<typename T = void, typename SFINAE = void>
|
||||
struct adl_serializer;
|
||||
|
||||
/// a class to store JSON values
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/
|
||||
template<template<typename U, typename V, typename... Args> class ObjectType =
|
||||
std::map,
|
||||
template<typename U, typename... Args> class ArrayType = std::vector,
|
||||
class StringType = std::string, class BooleanType = bool,
|
||||
class NumberIntegerType = std::int64_t,
|
||||
class NumberUnsignedType = std::uint64_t,
|
||||
class NumberFloatType = double,
|
||||
template<typename U> class AllocatorType = std::allocator,
|
||||
template<typename T, typename SFINAE = void> class JSONSerializer =
|
||||
adl_serializer,
|
||||
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
|
||||
class CustomBaseClass = void>
|
||||
class basic_json;
|
||||
|
||||
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
|
||||
/// @sa https://json.nlohmann.me/api/json_pointer/
|
||||
template<typename RefStringType>
|
||||
class json_pointer;
|
||||
|
||||
/*!
|
||||
@brief default specialization
|
||||
@sa https://json.nlohmann.me/api/json/
|
||||
*/
|
||||
using json = basic_json<>;
|
||||
|
||||
/// @brief a minimal map-like container that preserves insertion order
|
||||
/// @sa https://json.nlohmann.me/api/ordered_map/
|
||||
template<class Key, class T, class IgnoredLess, class Allocator>
|
||||
struct ordered_map;
|
||||
|
||||
/// @brief specialization that maintains the insertion order of object keys
|
||||
/// @sa https://json.nlohmann.me/api/ordered_json/
|
||||
using ordered_json = basic_json<nlohmann::ordered_map>;
|
||||
|
||||
NLOHMANN_JSON_NAMESPACE_END
|
||||
|
||||
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
36
src/utils/logger.c
Normal file
36
src/utils/logger.c
Normal file
@ -0,0 +1,36 @@
|
||||
#ifdef DEBUG
|
||||
#include <stdint.h>
|
||||
#include <whb/log_cafe.h>
|
||||
#include <whb/log_module.h>
|
||||
#include <whb/log_udp.h>
|
||||
|
||||
uint32_t moduleLogInit = false;
|
||||
uint32_t cafeLogInit = false;
|
||||
uint32_t udpLogInit = false;
|
||||
#endif // DEBUG
|
||||
|
||||
void initLogging() {
|
||||
#ifdef DEBUG
|
||||
if (!(moduleLogInit = WHBLogModuleInit())) {
|
||||
cafeLogInit = WHBLogCafeInit();
|
||||
udpLogInit = WHBLogUdpInit();
|
||||
}
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
void deinitLogging() {
|
||||
#ifdef DEBUG
|
||||
if (moduleLogInit) {
|
||||
WHBLogModuleDeinit();
|
||||
moduleLogInit = false;
|
||||
}
|
||||
if (cafeLogInit) {
|
||||
WHBLogCafeDeinit();
|
||||
cafeLogInit = false;
|
||||
}
|
||||
if (udpLogInit) {
|
||||
WHBLogUdpDeinit();
|
||||
udpLogInit = false;
|
||||
}
|
||||
#endif // DEBUG
|
||||
}
|
74
src/utils/logger.h
Normal file
74
src/utils/logger.h
Normal file
@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include <coreinit/debug.h>
|
||||
#include <string.h>
|
||||
#include <whb/log.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LOG_APP_TYPE "P"
|
||||
#define LOG_APP_NAME "AromaBasePlugin"
|
||||
|
||||
#define __FILENAME__ ({ \
|
||||
const char *__filename = __FILE__; \
|
||||
const char *__pos = strrchr(__filename, '/'); \
|
||||
if (!__pos) __pos = strrchr(__filename, '\\'); \
|
||||
__pos ? __pos + 1 : __filename; \
|
||||
})
|
||||
|
||||
#define LOG(LOG_FUNC, FMT, ARGS...) LOG_EX_DEFAULT(LOG_FUNC, "", "", FMT, ##ARGS)
|
||||
|
||||
#define LOG_EX_DEFAULT(LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) LOG_EX(__FILENAME__, __FUNCTION__, __LINE__, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ##ARGS)
|
||||
|
||||
#define LOG_EX(FILENAME, FUNCTION, LINE, LOG_FUNC, LOG_LEVEL, LINE_END, FMT, ARGS...) \
|
||||
do { \
|
||||
LOG_FUNC("[(%s)%18s][%23s]%30s@L%04d: " LOG_LEVEL "" FMT "" LINE_END, LOG_APP_TYPE, LOG_APP_NAME, FILENAME, FUNCTION, LINE, ##ARGS); \
|
||||
} while (0)
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#ifdef VERBOSE_DEBUG
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) LOG(WHBLogPrintf, FMT, ##ARGS)
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE_EX(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, WHBLogPrintf, "", "", FMT, ##ARGS);
|
||||
#else
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE_EX(FMT, ARGS...) while (0)
|
||||
#endif
|
||||
|
||||
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) LOG(WHBLogPrintf, FMT, ##ARGS)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) LOG(WHBLogWritef, FMT, ##ARGS)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX_DEFAULT(WHBLogPrintf, "##ERROR## ", "", FMT, ##ARGS)
|
||||
#define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX_DEFAULT(WHBLogPrintf, "##WARN ## ", "", FMT, ##ARGS)
|
||||
#define DEBUG_FUNCTION_LINE_INFO(FMT, ARGS...) LOG_EX_DEFAULT(WHBLogPrintf, "##INFO ## ", "", FMT, ##ARGS)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_ERR_LAMBDA(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, WHBLogPrintf, "##ERROR## ", "", FMT, ##ARGS);
|
||||
|
||||
#else
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE_EX(FMT, ARGS...) while (0)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_VERBOSE(FMT, ARGS...) while (0)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE(FMT, ARGS...) while (0)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) while (0)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_ERR(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##ERROR## ", "\n", FMT, ##ARGS)
|
||||
#define DEBUG_FUNCTION_LINE_WARN(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##WARN ## ", "\n", FMT, ##ARGS)
|
||||
#define DEBUG_FUNCTION_LINE_INFO(FMT, ARGS...) LOG_EX_DEFAULT(OSReport, "##INFO ## ", "\n", FMT, ##ARGS)
|
||||
|
||||
#define DEBUG_FUNCTION_LINE_ERR_LAMBDA(FILENAME, FUNCTION, LINE, FMT, ARGS...) LOG_EX(FILENAME, FUNCTION, LINE, OSReport, "##ERROR## ", "\n", FMT, ##ARGS);
|
||||
|
||||
#endif
|
||||
|
||||
void initLogging();
|
||||
|
||||
void deinitLogging();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
2
src/version.h
Normal file
2
src/version.h
Normal file
@ -0,0 +1,2 @@
|
||||
#pragma once
|
||||
#define PLUGIN_VERSION_EXTRA ""
|
Loading…
Reference in New Issue
Block a user