mirror of
https://github.com/wiiu-env/SwipSwapMe.git
synced 2024-11-21 20:29:14 +01:00
Port plugin to Aroma
This commit is contained in:
parent
65aec45c62
commit
567e286b6e
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"
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,2 +1,7 @@
|
|||||||
build/*
|
build/*
|
||||||
*.mod
|
*.mod
|
||||||
|
cmake-build-debug/
|
||||||
|
.idea/
|
||||||
|
*.wps
|
||||||
|
*.elf
|
||||||
|
CMakeLists.txt
|
||||||
|
31
.travis.yml
31
.travis.yml
@ -1,31 +0,0 @@
|
|||||||
sudo: required
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
services:
|
|
||||||
- docker
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- p7zip-full
|
|
||||||
before_script:
|
|
||||||
- docker build . -t swipswapme-builder
|
|
||||||
script:
|
|
||||||
- docker run -it --rm -v ${PWD}:/project swipswapme-builder make
|
|
||||||
before_deploy:
|
|
||||||
- cd $TRAVIS_BUILD_DIR/
|
|
||||||
- mkdir -p "wiiu/plugins"
|
|
||||||
- commit="$(git rev-parse --short=7 HEAD)"
|
|
||||||
- find -type f -name "*.mod" | xargs -i cp {} wiiu/plugins
|
|
||||||
- zip -r swipswapme_nightly_$commit.zip wiiu
|
|
||||||
- git config --local user.name "Maschell"
|
|
||||||
- git config --local user.email "Maschell@gmx.de"
|
|
||||||
- git tag "SwipSwapMe-$(date +'%Y%m%d%H%M%S')-$(git log --format=%h -1)"
|
|
||||||
deploy:
|
|
||||||
provider: releases
|
|
||||||
skip_cleanup: true
|
|
||||||
api_key:
|
|
||||||
secure: Gqu3sySILamrn1sY2Hcr32DHHXHvffzPg6uIR9gsJxMLReZT+OU4x9Pys88epPqpQCAnwbmoJYDSBrUTAumfwLxBeBv4FzySL87Ztbv9JLIvOakwNAi0d0dAtHYl7D/+2JlU57pY2CYK/k/Y/kKz0WswAi2QYZ68uY028l+2dc5a2y4L06ZMqbd3xWIzBGxgyJurmMXrHGdsiLz+2WEbDf/9dSuBrwjqGC5StfmupOwZVIBivZgrQz/g9Y8snK4FDPuR2eLOZKxas1QxcjFKI5hWlex/oHpxD41Zy5DyfawvgZU3YmScCJs/BzaOBkEs3boHbC199ppHCB0fl/GFgHdlmVmjdKOKJhuhRbj5zLKoEem0ujFi6MQF+OBHdEFhgpqC+CWuz+HZR3M/2p/e90W/0ZJOhWpWUWaIFLnQJ3abXAbd0oqnqJCbPZI5m7z+N/cNjGAJg/AQqYi/ophT4+Nh+9zNcDRtOwY8eQsYXKMCGOiaP/84LaO708TJQJFpY2GScorVrCWdFW/BPOU/RICLdKlBP6ljaMsC+TYFlJv1VRAh2+gLC8kNO5tdG6oNMYHgAPTGS45AHhIJNSiUOL0DhuTbrFEHVsae8uzmMdgxnQQVMRf17UVr7t5Dsap2CdD36eZspbPjmin4xFfaUxPoUoVrfwaSPpsWQJH+vYA=
|
|
||||||
file: swipswapme_nightly_$commit.zip
|
|
||||||
on:
|
|
||||||
repo: Maschell/SwipSwapMe
|
|
@ -1,6 +1,7 @@
|
|||||||
FROM wups/core-with-wut:0.1
|
FROM wiiuenv/devkitppc:20221228
|
||||||
|
|
||||||
# Get dependencies
|
COPY --from=wiiuenv/wiiupluginsystem:20230215 /artifacts $DEVKITPRO
|
||||||
COPY --from=wiiuwut/libutils:0.1 /artifacts $WUT_ROOT
|
COPY --from=wiiuenv/libnotifications:20230126 /artifacts $DEVKITPRO
|
||||||
|
COPY --from=wiiuenv/libmappedmemory:20220904 /artifacts $DEVKITPRO
|
||||||
|
|
||||||
WORKDIR project
|
WORKDIR project
|
||||||
|
353
Makefile
353
Makefile
@ -1,300 +1,147 @@
|
|||||||
# You probably never need to adjust this Makefile.
|
#-------------------------------------------------------------------------------
|
||||||
# All changes can be done in the makefile.mk
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# Clear the implicit built in rules
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
#---------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
ifeq ($(strip $(DEVKITPPC)),)
|
|
||||||
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
|
|
||||||
endif
|
|
||||||
ifeq ($(strip $(DEVKITPRO)),)
|
ifeq ($(strip $(DEVKITPRO)),)
|
||||||
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>devkitPRO")
|
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
export PATH := $(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH)
|
TOPDIR ?= $(CURDIR)
|
||||||
export PORTLIBS := $(DEVKITPRO)/portlibs/ppc
|
|
||||||
export WUPSDIR := $(DEVKITPRO)/wups
|
|
||||||
export GCC_VER := $(shell $(DEVKITPPC)/bin/powerpc-eabi-gcc -dumpversion)
|
|
||||||
|
|
||||||
PREFIX := powerpc-eabi-
|
include $(DEVKITPRO)/wups/share/wups_rules
|
||||||
|
|
||||||
export AS := $(PREFIX)as
|
WUT_ROOT := $(DEVKITPRO)/wut
|
||||||
export CC := $(PREFIX)gcc
|
WUMS_ROOT := $(DEVKITPRO)/wums
|
||||||
export CXX := $(PREFIX)g++
|
|
||||||
export LD := $(PREFIX)ld
|
|
||||||
export AR := $(PREFIX)ar
|
|
||||||
export OBJCOPY := $(PREFIX)objcopy
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# TARGET is the name of the output
|
# TARGET is the name of the output
|
||||||
# BUILD is the directory where object files & intermediate files will be placed
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
# SOURCES is a list of directories containing source code
|
# SOURCES is a list of directories containing source code
|
||||||
# INCLUDES is a list of directories containing extra header files
|
# DATA is a list of directories containing data files
|
||||||
#---------------------------------------------------------------------------------
|
# INCLUDES is a list of directories containing header files
|
||||||
TARGET := $(notdir $(CURDIR))
|
#-------------------------------------------------------------------------------
|
||||||
|
TARGET := swipswapme
|
||||||
BUILD := build
|
BUILD := build
|
||||||
|
SOURCES := src src/utils
|
||||||
|
DATA := data
|
||||||
|
INCLUDES := src
|
||||||
|
|
||||||
ifeq ($(notdir $(CURDIR)),$(BUILD))
|
#-------------------------------------------------------------------------------
|
||||||
include ../makefile.mk
|
|
||||||
else
|
|
||||||
include makefile.mk
|
|
||||||
endif
|
|
||||||
|
|
||||||
include $(WUPSDIR)/plugin_makefile.mk
|
|
||||||
|
|
||||||
|
|
||||||
#MAP ?= $(TARGET:.mod=.map)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# options for code generation
|
# options for code generation
|
||||||
#---------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
CFLAGS := -Wall -O2 -ffunction-sections \
|
||||||
|
$(MACHDEP)
|
||||||
|
|
||||||
# -Os: optimise size
|
CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -D__WUPS__
|
||||||
# -Wall: generate lots of warnings
|
|
||||||
# -D__wiiu__: define the symbol __wiiu__ (used in some headers)
|
|
||||||
# -mcpu=750: enable processor specific compilation
|
|
||||||
# -meabi: enable eabi specific compilation
|
|
||||||
# -mhard-float: enable hardware floating point instructions
|
|
||||||
# -nostartfiles: Do not use the standard system startup files when linking
|
|
||||||
# -ffunction-sections: split up functions so linker can garbage collect
|
|
||||||
# -fdata-sections: split up data so linker can garbage collect
|
|
||||||
COMMON_CFLAGS := -Os -Wall -mcpu=750 -meabi -mhard-float -D__WIIU__ -nostartfiles -ffunction-sections -fdata-sections -Wl,-q $(COMMON_CFLAGS)
|
|
||||||
|
|
||||||
# -x c: compile as c code
|
CXXFLAGS := $(CFLAGS) -std=c++20 -fno-exceptions -fno-rtti
|
||||||
# -std=c11: use the c11 standard
|
|
||||||
CFLAGS := $(COMMON_CFLAGS) -x c -std=gnu11 $(CFLAGS)
|
|
||||||
|
|
||||||
# -x c: compile as c++ code
|
ASFLAGS := -g $(ARCH)
|
||||||
# -std=gnu++11: use the c++11 standard
|
LDFLAGS = -g $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) -T$(WUMS_ROOT)/share/libmappedmemory.ld $(WUPSSPECS)
|
||||||
CXXFLAGS := $(COMMON_CFLAGS) -x c++ -std=gnu++11 $(CXXFLAGS)
|
|
||||||
|
|
||||||
ifeq ($(DO_LOGGING), 1)
|
ifeq ($(DEBUG),1)
|
||||||
CFLAGS += -D__LOGGING__
|
CXXFLAGS += -DDEBUG -g
|
||||||
CXXFLAGS += -D__LOGGING__
|
CFLAGS += -DDEBUG -g
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
ifeq ($(DEBUG),VERBOSE)
|
||||||
# any extra ld flags
|
CXXFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
||||||
#--------------------------------------------------------------------------------
|
CFLAGS += -DDEBUG -DVERBOSE_DEBUG -g
|
||||||
# --gc-sections: remove unneeded symbols
|
|
||||||
# -Map: generate a map file
|
|
||||||
LDFLAGS += -Wl,-Map,$(notdir $@).map,--gc-sections
|
|
||||||
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
Q := @
|
|
||||||
MAKEFLAGS += --no-print-directory
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# any extra libraries we wish to link with the project
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
LIBS +=
|
|
||||||
#
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# list of directories containing libraries, this must be the top level containing
|
|
||||||
# include and lib
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
LIBDIRS +=
|
|
||||||
|
|
||||||
NEEDS_WUT := 0
|
|
||||||
|
|
||||||
ifeq ($(WUT_ENABLE_CPP), 1)
|
|
||||||
WUT_ENABLE_NEWLIB := 1
|
|
||||||
|
|
||||||
LDFLAGS += -Wl,-whole-archive,-lwutstdc++,-no-whole-archive
|
|
||||||
NEEDS_WUT := 1
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(WUT_ENABLE_NEWLIB), 1)
|
LIBS := -lwups -lnotifications -lmappedmemory -lwut
|
||||||
LDFLAGS += -Wl,-whole-archive,-lwutnewlib,-no-whole-archive
|
|
||||||
NEEDS_WUT := 1
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(WUT_DEFAULT_MALLOC), 1)
|
#-------------------------------------------------------------------------------
|
||||||
LDFLAGS += -Wl,-whole-archive,-lwutmalloc,-no-whole-archive
|
# list of directories containing libraries, this must be the top level
|
||||||
NEEDS_WUT := 1
|
# containing include and lib
|
||||||
endif
|
#-------------------------------------------------------------------------------
|
||||||
|
LIBDIRS := $(PORTLIBS) $(WUPS_ROOT) $(WUT_ROOT) $(WUMS_ROOT)
|
||||||
|
|
||||||
ifeq ($(NEEDS_WUT), 1)
|
#-------------------------------------------------------------------------------
|
||||||
ifeq ($(strip $(WUT_ROOT)),)
|
|
||||||
$(error "Please set WUT_ROOT in your environment. export WUT_ROOT=<path to>wut)
|
|
||||||
endif
|
|
||||||
CFLAGS += -D__WUT__
|
|
||||||
CXXFLAGS += -D__WUT__
|
|
||||||
endif
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# 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
|
||||||
# rules for different file extensions
|
# rules for different file extensions
|
||||||
#---------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
#---------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
export PROJECTDIR := $(CURDIR)
|
|
||||||
export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET)
|
|
||||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
|
||||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
|
||||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# automatically build a list of object files for our project
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
|
||||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
|
||||||
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
|
||||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
|
|
||||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
|
||||||
TTFFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.ttf)))
|
|
||||||
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# use CXX for linking C++ projects, CC for standard C
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
ifeq ($(strip $(CPPFILES)),)
|
|
||||||
export REAL_LD := $(CC)
|
|
||||||
else
|
|
||||||
export REAL_LD := $(CXX)
|
|
||||||
endif
|
|
||||||
|
|
||||||
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
|
|
||||||
$(sFILES:.s=.o) $(SFILES:.S=.o) \
|
|
||||||
$(PNGFILES:.png=.png.o) $(addsuffix .o,$(BINFILES))
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# build a list of include paths
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
export INCLUDE_FULL += $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
|
||||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
|
||||||
$(EXTERNAL_INCLUDE)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# build a list of library paths
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
export LIBPATHS_FULL += $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
|
|
||||||
$(EXTERNAL_LIBPATHS)
|
|
||||||
|
|
||||||
|
|
||||||
export OUTPUT := $(CURDIR)/$(TARGET)
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
.PHONY: $(BUILD) clean install
|
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):
|
$(BUILD):
|
||||||
@[ -d $@ ] || mkdir -p $@
|
@$(shell [ ! -d $(BUILD) ] && mkdir -p $(BUILD))
|
||||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
clean:
|
clean:
|
||||||
@echo clean ...
|
@echo clean ...
|
||||||
@rm -fr $(BUILD) $(OUTPUT).mod $(OUTPUT)
|
@rm -fr $(BUILD) $(TARGET).wps $(TARGET).elf
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
else
|
else
|
||||||
|
.PHONY: all
|
||||||
|
|
||||||
DEPENDS := $(OFILES:.o=.d)
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
THIS_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
#-------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
all : $(OUTPUT).wps
|
||||||
|
|
||||||
###############################################################################
|
$(OUTPUT).wps : $(OUTPUT).elf
|
||||||
# Rule to make everything.
|
$(OUTPUT).elf : $(OFILES)
|
||||||
PHONY += all
|
|
||||||
|
|
||||||
all : $(OUTPUT)
|
$(OFILES_SRC) : $(HFILES_BIN)
|
||||||
###############################################################################
|
|
||||||
# Special build rules
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
# Rule to make the module file.
|
# you need a rule like this for each extension you use as binary data
|
||||||
$(OUTPUT) : $(OFILES)
|
#-------------------------------------------------------------------------------
|
||||||
@echo "linking ... " $@
|
%.bin.o %_bin.h : %.bin
|
||||||
@$(REAL_LD) $(OFILES) $(LDFLAGS) $(LIBS) $(LIBPATHS_FULL) -o $@
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Standard build rules
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.a:
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
@echo $(notdir $@)
|
|
||||||
@rm -f $@
|
|
||||||
@$(AR) -rc $@ $^
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.o: %.cpp
|
|
||||||
@echo $(notdir $<)
|
@echo $(notdir $<)
|
||||||
@$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) $(INCLUDE_FULL) -c $< -o $@ $(ERROR_FILTER)
|
@$(bin2o)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.o: %.c
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) $(INCLUDE_FULL) -c $< -o $@ $(ERROR_FILTER)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.o: %.S
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(INCLUDE_FULL) -c $< -o $@ $(ERROR_FILTER)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.png.o : %.png
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.jpg.o : %.jpg
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.ttf.o : %.ttf
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.bin.o : %.bin
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.wav.o : %.wav
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.mp3.o : %.mp3
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
%.ogg.o : %.ogg
|
|
||||||
@echo $(notdir $<)
|
|
||||||
@bin2s -a 32 $< | $(AS) -o $(@)
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Assembly listing rules
|
|
||||||
|
|
||||||
# Rule to make assembly listing.
|
|
||||||
PHONY += list
|
|
||||||
list : $(LIST)
|
|
||||||
|
|
||||||
# Rule to make the listing file.
|
|
||||||
%.list : $(TARGET)
|
|
||||||
$(LOG)
|
|
||||||
-$Qmkdir -p $(dir $@)
|
|
||||||
$Q$(OBJDUMP) -d $< > $@
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Clean rule
|
|
||||||
|
|
||||||
# Rule to clean files.
|
|
||||||
PHONY += clean
|
|
||||||
clean :
|
|
||||||
$Qrm -rf $(wildcard $(BUILD) $(BIN))
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Phony targets
|
|
||||||
|
|
||||||
.PHONY : $(PHONY)
|
|
||||||
|
|
||||||
-include $(DEPENDS)
|
-include $(DEPENDS)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
endif
|
endif
|
||||||
#---------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
75
README.md
75
README.md
@ -1,32 +1,69 @@
|
|||||||
# SwipSwapMe Plugin for the Wii U Plugin System [![Build Status](https://api.travis-ci.org/Maschell/SwipSwapMe.svg?branch=master)](https://travis-ci.org/Maschell/SwipSwapMe)
|
# SwipSwapMe Plugin
|
||||||
|
|
||||||
This little app can be used to swap the TV and DRC screen.
|
This little plugin can be used to swap the TV and GamePad screen and offers different audio modes.
|
||||||
|
|
||||||
# Wii U Plugin System
|
**When this plugin is enabled, the audio output of your Wii U is forced to stereo**
|
||||||
This is a plugin for the [Wii U Plugin System (WUPS)](https://github.com/Maschell/WiiUPluginSystem/). To be able to use this plugin you have to place the resulting `.mod` file into the following folder:
|
|
||||||
|
|
||||||
```
|
## Installation
|
||||||
sd:/wiiu/plugins
|
|
||||||
```
|
|
||||||
When the file is placed on the SDCard you can load it with [plugin loader](https://github.com/Maschell/WiiUPluginSystem/).
|
|
||||||
|
|
||||||
# Usage
|
(`[ENVIRONMENT]` is a placeholder for the actual environment name.)
|
||||||
|
|
||||||
When starting the app, you have the option to set your own button combo. Just press the button combo you want for 2 seconds.
|
1. Copy the file `swipswapme.wps` into `sd:/wiiu/environments/[ENVIRONMENT]/plugins`.
|
||||||
Otherwise it will use the default settings (TV button).
|
2. Requires the [WiiUPluginLoaderBackend](https://github.com/wiiu-env/WiiUPluginLoaderBackend) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
|
||||||
|
3. Requires the [MemoryMappingModule](https://github.com/wiiu-env/MemoryMappingModule) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
|
||||||
|
4. Requires the [NotificationModule](https://github.com/wiiu-env/NotificationModule) in `sd:/wiiu/environments/[ENVIRONMENT]/modules`.
|
||||||
|
|
||||||
Press the TV button (or your button combo) on the Gamepad to swap the screens. Thats all.
|
## Usage
|
||||||
|
|
||||||
|
Press a button combo (default is the GamePad's TV button) on the GamePad, Pro Controller or Classic Controller to take swap the screens.
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
- **Settings**:
|
||||||
|
- Plugin enabled: (Default is true)
|
||||||
|
- Enables or disables the SwipSwapMe plugin. **Forces the audio output to stereo when enabled.**
|
||||||
|
- Show notifications: (Default is true)
|
||||||
|
- Displays notifications when swapping the screens or changing the audio mode.
|
||||||
|
- Swap screens: (Default is false)
|
||||||
|
- Swaps the TV and GamePad screen when set to true.
|
||||||
|
- Audio mode: (Default is "Sound matches screen")
|
||||||
|
- Sets the audio mode. See "Audio modes" for more details.
|
||||||
|
- **Button combos**
|
||||||
|
- Enable swap screen button combo: (Default is true)
|
||||||
|
- Determines if the screen can be swapped with a button combo.
|
||||||
|
- Swap screen: (Default is the "TV" button)
|
||||||
|
- Button combo to swap the TV and GamePad screen.
|
||||||
|
- Enable change audio mode button combo: (Default is false)
|
||||||
|
- Determines if the audio mode can be changed via a button combo.
|
||||||
|
- Change audio: (Default is "left stick button"/L3)
|
||||||
|
- Button combo to change the audio mode.
|
||||||
|
|
||||||
|
#### Audio Modes
|
||||||
|
|
||||||
|
SwipSwapme does not only allow you to swap the screen, it also offers multiple audio modes:
|
||||||
|
|
||||||
|
- **Normal**
|
||||||
|
- The audio output is not touched at all.
|
||||||
|
- **Swap TV and GamePad sound**
|
||||||
|
- Swaps the audio output of the TV and GamePad regardless of the screen swapping.
|
||||||
|
- **Sound matches screen**
|
||||||
|
- Swaps the audio output of the TV and GamePad if the screen are swapped as well.
|
||||||
|
- **Combine TV and GamePad sound**
|
||||||
|
- Outputs the TV and GamePad sound on both.
|
||||||
|
- **Left: TV; Right: GamePad**
|
||||||
|
- Outputs the TV sound on the left speaker, and the GamePad sound on the right speaker.
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
For building you need:
|
For building you need:
|
||||||
- [wups](https://github.com/Maschell/WiiUPluginSystem)
|
|
||||||
- [wut](https://github.com/decaf-emu/wut)
|
|
||||||
- [libutilswut](https://github.com/Maschell/libutils/tree/wut) (WUT version) for common functions.
|
|
||||||
|
|
||||||
Install them (in this order) according to their README's. Don't forget the dependencies of the libs itself.
|
- [wups](https://github.com/wiiu-env/WiiUPluginSystem)
|
||||||
|
- [wut](https://github.com/devkitPro/wut)
|
||||||
|
- [libnotifications](https://github.com/wiiu-env/libnotifications)
|
||||||
|
- [libmappedmemory](https://github.com/wiiu-env/libmappedmemory)
|
||||||
|
|
||||||
|
## Building using the Dockerfile
|
||||||
|
|
||||||
### 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.
|
It's possible to use a docker image for building. This way you don't need anything installed on your host system.
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -39,3 +76,7 @@ docker run -it --rm -v ${PWD}:/project swipswapme-builder make
|
|||||||
# make clean
|
# make clean
|
||||||
docker run -it --rm -v ${PWD}:/project swipswapme-builder make clean
|
docker run -it --rm -v ${PWD}:/project swipswapme-builder make clean
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Format the code via docker
|
||||||
|
|
||||||
|
`docker run --rm -v ${PWD}:/src wiiuenv/clang-format:13.0.0-2 -r ./src -i`
|
||||||
|
66
makefile.mk
66
makefile.mk
@ -1,66 +0,0 @@
|
|||||||
# Compiling the projects with libutils logging code?
|
|
||||||
DO_LOGGING := 1
|
|
||||||
|
|
||||||
# Links against the wut implementation of newlib, this is useful for using any function
|
|
||||||
# from the C standard library
|
|
||||||
WUT_ENABLE_NEWLIB := 0
|
|
||||||
|
|
||||||
# Links against the wut implementation of stdcpp, this is useful for using any function
|
|
||||||
# from the C++ standard library. This will enable WUT_ENABLE_NEWLIB if you have not already done so.
|
|
||||||
WUT_ENABLE_CPP := 0
|
|
||||||
|
|
||||||
# By default newlib will allocate 90% of the default heap for use with sbrk & malloc,
|
|
||||||
# if this is unacceptable to you then you should use this as it replaces the newlib
|
|
||||||
# malloc functions which ones which redirect to the CafeOS default heap functions
|
|
||||||
# such as MEMAllocFromDefaultHeap.
|
|
||||||
WUT_DEFAULT_MALLOC := 1
|
|
||||||
|
|
||||||
# Target filename
|
|
||||||
TARGET := swipswapme.mod
|
|
||||||
|
|
||||||
# Source directories
|
|
||||||
SOURCES := src/ \
|
|
||||||
src/common \
|
|
||||||
src/utils \
|
|
||||||
|
|
||||||
# Data directories
|
|
||||||
DATA :=
|
|
||||||
|
|
||||||
# Include directories
|
|
||||||
INCLUDES := src
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# options for code generation and linking
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# Extra C AND C++ compiler flags
|
|
||||||
COMMON_CFLAGS :=
|
|
||||||
# Extra C compiler flags
|
|
||||||
CFLAGS :=
|
|
||||||
# Extra C++ compiler flags
|
|
||||||
CXXFLAGS :=
|
|
||||||
# Extra linking flags for all linking steps
|
|
||||||
LDFLAGS :=
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# list of directories containing libraries, this must be the top level containing
|
|
||||||
# include and lib
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
LIBDIRS := $(WUPSDIR) $(WUT_ROOT)
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# any extra libraries we wish to link with the project
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
LIBS := -lwups -lutilswut -lcoreinit -lvpad -lnsysnet
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# Will be added to the final lib paths
|
|
||||||
# example:
|
|
||||||
# -L$C:/library1/lib
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
EXTERNAL_LIBPATHS :=
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
# Will be added to the final include paths
|
|
||||||
# -IC:/library1/include
|
|
||||||
#---------------------------------------------------------------------------------
|
|
||||||
EXTERNAL_INCLUDE := -I$(WUT_ROOT)/include/libutilswut
|
|
@ -1,24 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2017,2018 Maschell
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#include "common/c_retain_vars.h"
|
|
||||||
|
|
||||||
uint8_t gSwap __attribute__((section(".data"))) = 0;
|
|
||||||
uint8_t gCallbackCooldown __attribute__((section(".data"))) = 0;
|
|
||||||
uint8_t gAppStatus __attribute__((section(".data"))) = 0;
|
|
||||||
uint32_t gButtonCombo __attribute__((section(".data"))) = 0;
|
|
||||||
|
|
||||||
VoiceInfo gVoiceInfos[VOICE_INFO_MAX] __attribute__((section(".data")));
|
|
@ -1,27 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2017,2018 Maschell
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#ifndef C_RETAINS_VARS_H_
|
|
||||||
#define C_RETAINS_VARS_H_
|
|
||||||
|
|
||||||
#include "utils/voice_info.h"
|
|
||||||
extern uint8_t gSwap;
|
|
||||||
extern uint8_t gCallbackCooldown;
|
|
||||||
extern uint8_t gAppStatus;
|
|
||||||
extern uint32_t gButtonCombo;
|
|
||||||
extern VoiceInfo gVoiceInfos[VOICE_INFO_MAX];
|
|
||||||
|
|
||||||
#endif // C_RETAINS_VARS_H_
|
|
@ -14,106 +14,315 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include <wups.h>
|
#include "retain_vars.hpp"
|
||||||
|
#include "utils/input.h"
|
||||||
|
#include "utils/logger.h"
|
||||||
|
#include <coreinit/dynload.h>
|
||||||
|
#include <gx2/surface.h>
|
||||||
#include <gx2/swap.h>
|
#include <gx2/swap.h>
|
||||||
|
#include <memory/mappedmemory.h>
|
||||||
|
#include <notifications/notifications.h>
|
||||||
|
#include <padscore/wpad.h>
|
||||||
#include <vpad/input.h>
|
#include <vpad/input.h>
|
||||||
#include <utils/logger.h>
|
#include <wups.h>
|
||||||
|
|
||||||
#include "utils/voice_swapper.h"
|
void UpdateAudioMode();
|
||||||
#include "common/c_retain_vars.h"
|
|
||||||
|
|
||||||
DECL_FUNCTION(int32_t, AXSetVoiceDeviceMixOld, void *v, int32_t device, uint32_t id, void *mix){
|
DECL_FUNCTION(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer *colorBuffer, GX2ScanTarget scan_target) {
|
||||||
if(gSwap){ device = !device;}
|
if (gEnabled && gDoScreenSwap) {
|
||||||
if(VOICE_SWAP_LOG == 1){log_printf("AXSetVoiceDeviceMixOld voice: %08X device: %d, mix: %08X\n",v,device,mix);}
|
if (scan_target == GX2_SCAN_TARGET_TV) {
|
||||||
VoiceSwapper_setMix(v,device,mix);
|
scan_target = GX2_SCAN_TARGET_DRC;
|
||||||
return real_AXSetVoiceDeviceMixOld(v,device,id,mix);
|
} else if (scan_target == GX2_SCAN_TARGET_DRC) {
|
||||||
|
scan_target = GX2_SCAN_TARGET_TV;
|
||||||
|
}
|
||||||
|
if (colorBuffer->surface.aa != GX2_AA_MODE1X) {
|
||||||
|
// If AA is enabled, we need to resolve the AA buffer.
|
||||||
|
GX2Surface tempSurface;
|
||||||
|
tempSurface = colorBuffer->surface;
|
||||||
|
tempSurface.aa = GX2_AA_MODE1X;
|
||||||
|
GX2CalcSurfaceSizeAndAlignment(&tempSurface);
|
||||||
|
|
||||||
|
tempSurface.image = MEMAllocFromMappedMemoryForGX2Ex(tempSurface.imageSize, tempSurface.alignment);
|
||||||
|
if (tempSurface.image != nullptr) {
|
||||||
|
GX2ResolveAAColorBuffer(colorBuffer, &tempSurface, 0, 0);
|
||||||
|
|
||||||
|
auto surfaceCpy = colorBuffer->surface;
|
||||||
|
colorBuffer->surface = tempSurface;
|
||||||
|
real_GX2CopyColorBufferToScanBuffer(colorBuffer, scan_target);
|
||||||
|
colorBuffer->surface = surfaceCpy;
|
||||||
|
|
||||||
|
if (tempSurface.image != nullptr) {
|
||||||
|
MEMFreeToMappedMemory(tempSurface.image);
|
||||||
|
tempSurface.image = nullptr;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to allocate %d bytes for resolving AA", tempSurface.imageSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
real_GX2CopyColorBufferToScanBuffer(colorBuffer, scan_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
DECL_FUNCTION(int32_t, AXSetVoiceDeviceMix, void *v, int32_t device, uint32_t id, void *mix){
|
void SwapScreens() {
|
||||||
if(gSwap){ device = !device;}
|
gDoScreenSwap = !gDoScreenSwap;
|
||||||
if(VOICE_SWAP_LOG == 1){log_printf("AXSetVoiceDeviceMix voice: %08X device: %d, mix: %08X\n",v,device,mix);}
|
|
||||||
VoiceSwapper_setMix(v,device,mix);
|
if (gShowNotifications && gNotificationModuleInitDone) {
|
||||||
return real_AXSetVoiceDeviceMix(v,device,id,mix);
|
if (gDoScreenSwap) {
|
||||||
|
NotificationModule_AddInfoNotification("Swapping TV and GamePad screen");
|
||||||
|
} else {
|
||||||
|
NotificationModule_AddInfoNotification("Stop swapping TV and GamePad screen");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DECL_FUNCTION(void *, AXAcquireVoiceExOld, uint32_t prio, void * callback, uint32_t arg){
|
void SwapVoices();
|
||||||
void * result = real_AXAcquireVoiceExOld(prio,callback,arg);
|
extern "C" uint32_t VPADGetButtonProcMode(VPADChan chan);
|
||||||
if(VOICE_SWAP_LOG == 1){log_printf("AXAcquireVoiceExOld result: %08X \n",result);}
|
|
||||||
VoiceSwapper_acquireVoice(result);
|
static uint32_t sSwapScreenWasHoldForXFrameGamePad;
|
||||||
|
static uint32_t sSwapVoicesWasHoldForXFrameGamePad;
|
||||||
|
DECL_FUNCTION(int32_t, VPADRead, VPADChan chan, VPADStatus *buffer, uint32_t buffer_size, VPADReadError *error) {
|
||||||
|
VPADReadError real_error;
|
||||||
|
int32_t result = real_VPADRead(chan, buffer, buffer_size, &real_error);
|
||||||
|
|
||||||
|
if (gEnabled && (gSwapScreenButtonComboEnabled || gChangeAudioModeButtonComboEnabled)) {
|
||||||
|
if (result > 0 && real_error == VPAD_READ_SUCCESS) {
|
||||||
|
// Fix games like TP HD
|
||||||
|
bool checkFullBuffer = VPADGetButtonProcMode(chan) == 1;
|
||||||
|
|
||||||
|
if (gChangeAudioModeButtonComboEnabled && checkButtonComboVPAD(buffer,
|
||||||
|
checkFullBuffer ? buffer_size : 1,
|
||||||
|
gSwapAudioButtonCombo,
|
||||||
|
sSwapVoicesWasHoldForXFrameGamePad)) {
|
||||||
|
SwapVoices();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gSwapScreenButtonComboEnabled && checkButtonComboVPAD(buffer,
|
||||||
|
checkFullBuffer ? buffer_size : 1,
|
||||||
|
gSwapScreenButtonCombo,
|
||||||
|
sSwapScreenWasHoldForXFrameGamePad)) {
|
||||||
|
SwapScreens();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
*error = real_error;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DECL_FUNCTION(void *, AXAcquireVoiceEx, uint32_t prio, void * callback, uint32_t arg){
|
const char *modeToStr(SwipSwapAudioMode mode) {
|
||||||
void * result = real_AXAcquireVoiceEx(prio,callback,arg);
|
switch (mode) {
|
||||||
if(VOICE_SWAP_LOG == 1){log_printf("AXAcquireVoiceEx result: %08X \n",result);}
|
case AUDIO_MODE_NONE:
|
||||||
VoiceSwapper_acquireVoice(result);
|
return "Audio mode: Normal";
|
||||||
return result;
|
case AUDIO_MODE_SWAP:
|
||||||
}
|
return "Audio mode: Swap TV and GamePad";
|
||||||
|
case AUDIO_MODE_MATCH_SCREEN:
|
||||||
DECL_FUNCTION(void, AXFreeVoiceOld, void *v){
|
return "Audio mode: Sound matches screen";
|
||||||
if(VOICE_SWAP_LOG == 1){log_printf("AXFreeVoiceOld v: %08X \n",v);}
|
case AUDIO_MODE_COMBINE:
|
||||||
VoiceSwapper_freeVoice(v);
|
return "Audio mode: Combine TV and GamePad";
|
||||||
real_AXFreeVoiceOld(v);
|
case AUDIO_MODE_LEFT_TV_RIGHT_DRC:
|
||||||
}
|
return "Audio mode: Left speaker TV, right speaker GamePad";
|
||||||
|
case AUDIO_MODE_MAX_VALUE:
|
||||||
DECL_FUNCTION(void, AXFreeVoice, void *v){
|
break;
|
||||||
if(VOICE_SWAP_LOG == 1){log_printf("AXFreeVoice v: %08X \n",v);}
|
|
||||||
VoiceSwapper_freeVoice(v);
|
|
||||||
real_AXFreeVoice(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
DECL_FUNCTION(void, GX2CopyColorBufferToScanBuffer, GX2ColorBuffer *colorBuffer, int32_t scan_target){
|
|
||||||
if(gSwap){
|
|
||||||
if(scan_target == 1){
|
|
||||||
scan_target = 4;
|
|
||||||
}else{
|
|
||||||
scan_target = 1;
|
|
||||||
}
|
}
|
||||||
}
|
return "Invalid audio mode";
|
||||||
real_GX2CopyColorBufferToScanBuffer(colorBuffer,scan_target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
void SwapVoices() {
|
||||||
DECL(int32_t, AXSetDefaultMixerSelectOld, uint32_t s){
|
auto val = (uint32_t) gCurAudioMode;
|
||||||
int32_t result = real_AXSetDefaultMixerSelectOld(s);
|
val++;
|
||||||
return result;
|
if (val >= AUDIO_MODE_MAX_VALUE) {
|
||||||
}*/
|
val = 0;
|
||||||
|
}
|
||||||
|
gCurAudioMode = static_cast<SwipSwapAudioMode>(val);
|
||||||
void swapVoices(){
|
if (gShowNotifications && gNotificationModuleInitDone) {
|
||||||
VoiceSwapper_swapAll();
|
NotificationModule_AddInfoNotification(modeToStr(gCurAudioMode));
|
||||||
for(int32_t i = 0;i<VOICE_INFO_MAX;i++){
|
|
||||||
if(gVoiceInfos[i].voice == NULL) continue;
|
|
||||||
|
|
||||||
real_AXSetVoiceDeviceMix(gVoiceInfos[i].voice,0,0,gVoiceInfos[i].mixTV);
|
|
||||||
real_AXSetVoiceDeviceMix(gVoiceInfos[i].voice,1,0,gVoiceInfos[i].mixDRC);
|
|
||||||
real_AXSetVoiceDeviceMixOld(gVoiceInfos[i].voice,0,0,gVoiceInfos[i].mixTV);
|
|
||||||
real_AXSetVoiceDeviceMixOld(gVoiceInfos[i].voice,1,0,gVoiceInfos[i].mixDRC);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DECL_FUNCTION(int32_t, VPADRead, int32_t chan, VPADStatus *buffer, uint32_t buffer_size, VPADReadError *error) {
|
static uint32_t sSwapScreenWasHoldForXFrame[4];
|
||||||
int32_t result = real_VPADRead(chan, buffer, buffer_size, error);
|
static uint32_t sSwapAudioWasHoldForXFrame[4];
|
||||||
|
DECL_FUNCTION(void, WPADRead, WPADChan chan, WPADStatusProController *data) {
|
||||||
|
real_WPADRead(chan, data);
|
||||||
|
|
||||||
if(result > 0 && *error == VPAD_READ_SUCCESS && ((buffer[0].hold & gButtonCombo) == gButtonCombo) && gCallbackCooldown == 0 ){
|
if (gEnabled && (gSwapScreenButtonComboEnabled || gChangeAudioModeButtonComboEnabled) && chan >= 0 && chan < 4) {
|
||||||
gCallbackCooldown = 0x3C;
|
if (data && data[0].err == 0) {
|
||||||
if(gAppStatus == WUPS_APP_STATUS_FOREGROUND){
|
if (data[0].extensionType != 0xFF) {
|
||||||
gSwap = !gSwap;
|
uint32_t curButtonHold = 0;
|
||||||
swapVoices();
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gSwapScreenButtonComboEnabled && checkButtonComboWPAD(curButtonHold, gSwapScreenButtonCombo, sSwapScreenWasHoldForXFrame[chan])) {
|
||||||
|
SwapScreens();
|
||||||
|
}
|
||||||
|
if (gChangeAudioModeButtonComboEnabled && checkButtonComboWPAD(curButtonHold, gSwapAudioButtonCombo, sSwapAudioWasHoldForXFrame[chan])) {
|
||||||
|
SwapVoices();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(gCallbackCooldown > 0) gCallbackCooldown--;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int16_t DRCCopy[0x120] = {};
|
||||||
|
int16_t TVCopy[0x120] = {};
|
||||||
|
typedef void (*AIInitDMAfn)(int16_t *addr, uint32_t size);
|
||||||
|
void DoAudioMagic(int16_t *addr, uint32_t size, bool isDRC, AIInitDMAfn targetFunc, AIInitDMAfn otherFunc) {
|
||||||
|
auto sizeCpy = size > 576 ? 576 : size;
|
||||||
|
if (!gEnabled) {
|
||||||
|
targetFunc(addr, size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (gCurAudioMode) {
|
||||||
|
case AUDIO_MODE_NONE:
|
||||||
|
break;
|
||||||
|
case AUDIO_MODE_SWAP:
|
||||||
|
otherFunc(addr, sizeCpy);
|
||||||
|
return;
|
||||||
|
case AUDIO_MODE_MATCH_SCREEN: {
|
||||||
|
if (gDoScreenSwap) {
|
||||||
|
otherFunc(addr, sizeCpy);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AUDIO_MODE_COMBINE:
|
||||||
|
case AUDIO_MODE_LEFT_TV_RIGHT_DRC: {
|
||||||
|
if (isDRC) {
|
||||||
|
memcpy(DRCCopy, addr, sizeCpy);
|
||||||
|
} else {
|
||||||
|
memcpy(TVCopy, addr, sizeCpy);
|
||||||
|
}
|
||||||
|
if (gCurAudioMode == AUDIO_MODE_COMBINE) {
|
||||||
|
for (uint32_t i = 0; i < 0x120; i += 2) {
|
||||||
|
// Combine left channel of TV and DRC
|
||||||
|
auto val = (((int32_t) TVCopy[i] + (int32_t) DRCCopy[i]) >> 1);
|
||||||
|
if (val > 0x7FFF) {
|
||||||
|
val = 0x7FFF;
|
||||||
|
} else if (val < -0x8000) {
|
||||||
|
val = 0x8000;
|
||||||
|
}
|
||||||
|
addr[i] = (int16_t) val;
|
||||||
|
// Combine right channel of TV and DRC
|
||||||
|
val = (((int32_t) TVCopy[i] + (int32_t) DRCCopy[i]) >> 1);
|
||||||
|
if (val > 0x7FFF) {
|
||||||
|
val = 0x7FFF;
|
||||||
|
} else if (val < -0x8000) {
|
||||||
|
val = 0x8000;
|
||||||
|
}
|
||||||
|
addr[i + 1] = (int16_t) val;
|
||||||
|
}
|
||||||
|
} else if (gCurAudioMode == AUDIO_MODE_LEFT_TV_RIGHT_DRC) {
|
||||||
|
for (uint32_t i = 0; i < 0x120; i += 2) {
|
||||||
|
// Mix down TV to MONO and put it in the left channel
|
||||||
|
auto val = (((int32_t) TVCopy[i] + (int32_t) TVCopy[i + 1]) >> 1);
|
||||||
|
if (val > 0x7FFF) {
|
||||||
|
val = 0x7FFF;
|
||||||
|
} else if (val < -0x8000) {
|
||||||
|
val = 0x8000;
|
||||||
|
}
|
||||||
|
addr[i] = (int16_t) val;
|
||||||
|
// Mix down DRC to MONO and put it in the right channel
|
||||||
|
val = (((int32_t) DRCCopy[i] + (int32_t) DRCCopy[i + 1]) >> 1);
|
||||||
|
if (val > 0x7FFF) {
|
||||||
|
val = 0x7FFF;
|
||||||
|
} else if (val < -0x8000) {
|
||||||
|
val = 0x8000;
|
||||||
|
}
|
||||||
|
addr[i + 1] = (int16_t) val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
gCurAudioMode = AUDIO_MODE_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
targetFunc(addr, sizeCpy);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void (*real_AIInitDMA)(int16_t *addr, uint32_t size) __attribute__((section(".data")));
|
||||||
|
extern "C" void (*real_AIInitDMA2)(int16_t *addr, uint32_t size) __attribute__((section(".data")));
|
||||||
|
|
||||||
|
DECL_FUNCTION(void, AI2InitDMA, int16_t *addr, uint32_t size) {
|
||||||
|
DoAudioMagic(addr, size, true, real_AI2InitDMA, real_AIInitDMA);
|
||||||
|
}
|
||||||
|
DECL_FUNCTION(void, AIInitDMA, int16_t *addr, uint32_t size) {
|
||||||
|
DoAudioMagic(addr, size, false, real_AIInitDMA, real_AI2InitDMA);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECL_FUNCTION(void, AI2InitDMA2, int16_t *addr, uint32_t size) {
|
||||||
|
DoAudioMagic(addr, size, true, real_AI2InitDMA2, real_AIInitDMA2);
|
||||||
|
}
|
||||||
|
DECL_FUNCTION(void, AIInitDMA2, int16_t *addr, uint32_t size) {
|
||||||
|
DoAudioMagic(addr, size, false, real_AIInitDMA2, real_AI2InitDMA2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sAvoidRecursiveCall = false;
|
||||||
|
DECL_FUNCTION(void, AXUpdateDeviceModes) {
|
||||||
|
if (!gEnabled) {
|
||||||
|
real_AXUpdateDeviceModes();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sAvoidRecursiveCall = true;
|
||||||
|
real_AXUpdateDeviceModes();
|
||||||
|
sAvoidRecursiveCall = false;
|
||||||
|
}
|
||||||
|
bool sAvoidRecursiveCall2 = false;
|
||||||
|
DECL_FUNCTION(void, AXUpdateDeviceModes2) {
|
||||||
|
if (!gEnabled) {
|
||||||
|
real_AXUpdateDeviceModes2();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sAvoidRecursiveCall2 = true;
|
||||||
|
real_AXUpdateDeviceModes2();
|
||||||
|
sAvoidRecursiveCall2 = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DECL_FUNCTION(uint32_t, AVMGetTVAudioMode, uint32_t *mode) {
|
||||||
|
auto res = real_AVMGetTVAudioMode(mode);
|
||||||
|
if (!gEnabled) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (*mode != 1) {
|
||||||
|
// force stereo
|
||||||
|
*mode = 1;
|
||||||
|
UpdateAudioMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAudioMode() {
|
||||||
|
OSDynLoad_Module mod = nullptr;
|
||||||
|
if (OSDynLoad_IsModuleLoaded("sndcore2", &mod) == OS_DYNLOAD_OK && mod != nullptr) {
|
||||||
|
if (real_AXUpdateDeviceModes2 != nullptr && !sAvoidRecursiveCall2) {
|
||||||
|
my_AXUpdateDeviceModes2();
|
||||||
|
}
|
||||||
|
} else if (OSDynLoad_IsModuleLoaded("snd_core", &mod) == OS_DYNLOAD_OK && mod != nullptr) {
|
||||||
|
if (real_AXUpdateDeviceModes != nullptr && !sAvoidRecursiveCall) {
|
||||||
|
my_AXUpdateDeviceModes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WUPS_MUST_REPLACE(GX2CopyColorBufferToScanBuffer, WUPS_LOADER_LIBRARY_GX2, GX2CopyColorBufferToScanBuffer);
|
WUPS_MUST_REPLACE(GX2CopyColorBufferToScanBuffer, WUPS_LOADER_LIBRARY_GX2, GX2CopyColorBufferToScanBuffer);
|
||||||
WUPS_MUST_REPLACE(VPADRead, WUPS_LOADER_LIBRARY_VPAD, VPADRead);
|
WUPS_MUST_REPLACE(VPADRead, WUPS_LOADER_LIBRARY_VPAD, VPADRead);
|
||||||
WUPS_MUST_REPLACE(AXAcquireVoiceExOld, WUPS_LOADER_LIBRARY_SND_CORE, AXAcquireVoiceEx);
|
WUPS_MUST_REPLACE(WPADRead, WUPS_LOADER_LIBRARY_PADSCORE, WPADRead);
|
||||||
WUPS_MUST_REPLACE(AXFreeVoiceOld, WUPS_LOADER_LIBRARY_SND_CORE, AXFreeVoice);
|
|
||||||
WUPS_MUST_REPLACE(AXSetVoiceDeviceMixOld, WUPS_LOADER_LIBRARY_SND_CORE, AXSetVoiceDeviceMix);
|
WUPS_MUST_REPLACE_FOR_PROCESS(AIInitDMA, WUPS_LOADER_LIBRARY_SND_CORE, AIInitDMA, WUPS_FP_TARGET_PROCESS_ALL);
|
||||||
//WUPS_MUST_REPLACE(AXSetDefaultMixerSelectOld, , WUPS_LOADER_LIBRARY_SND_CORE, AXSetDefaultMixerSelect),
|
WUPS_MUST_REPLACE_FOR_PROCESS(AI2InitDMA, WUPS_LOADER_LIBRARY_SND_CORE, AI2InitDMA, WUPS_FP_TARGET_PROCESS_ALL);
|
||||||
WUPS_MUST_REPLACE(AXAcquireVoiceEx, WUPS_LOADER_LIBRARY_SNDCORE2, AXAcquireVoiceEx);
|
WUPS_MUST_REPLACE_FOR_PROCESS(AIInitDMA2, WUPS_LOADER_LIBRARY_SNDCORE2, AIInitDMA, WUPS_FP_TARGET_PROCESS_ALL);
|
||||||
WUPS_MUST_REPLACE(AXFreeVoice, WUPS_LOADER_LIBRARY_SNDCORE2, AXFreeVoice);
|
WUPS_MUST_REPLACE_FOR_PROCESS(AI2InitDMA2, WUPS_LOADER_LIBRARY_SNDCORE2, AI2InitDMA, WUPS_FP_TARGET_PROCESS_ALL);
|
||||||
WUPS_MUST_REPLACE(AXSetVoiceDeviceMix, WUPS_LOADER_LIBRARY_SNDCORE2, AXSetVoiceDeviceMix);
|
|
||||||
|
WUPS_MUST_REPLACE_FOR_PROCESS(AVMGetTVAudioMode, WUPS_LOADER_LIBRARY_AVM, AVMGetTVAudioMode, WUPS_FP_TARGET_PROCESS_ALL);
|
||||||
|
WUPS_MUST_REPLACE_FOR_PROCESS(AXUpdateDeviceModes, WUPS_LOADER_LIBRARY_SND_CORE, AXUpdateDeviceModes, WUPS_FP_TARGET_PROCESS_ALL);
|
||||||
|
WUPS_MUST_REPLACE_FOR_PROCESS(AXUpdateDeviceModes2, WUPS_LOADER_LIBRARY_SNDCORE2, AXUpdateDeviceModes, WUPS_FP_TARGET_PROCESS_ALL);
|
||||||
|
190
src/main.cpp
190
src/main.cpp
@ -14,141 +14,85 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
#include "main.h"
|
||||||
#include <string.h>
|
#include "retain_vars.hpp"
|
||||||
#include <stdlib.h>
|
#include "utils/WUPSConfigItemButtonCombo.h"
|
||||||
#include <stdio.h>
|
#include "utils/config.h"
|
||||||
#include <malloc.h>
|
#include "utils/logger.h"
|
||||||
|
#include <notifications/notifications.h>
|
||||||
|
#include <string>
|
||||||
#include <wups.h>
|
#include <wups.h>
|
||||||
|
|
||||||
#include <vector>
|
// Mandatory plugin information.
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <vpad/input.h>
|
|
||||||
#include <coreinit/screen.h>
|
|
||||||
#include <coreinit/thread.h>
|
|
||||||
#include <common/c_retain_vars.h>
|
|
||||||
#include <nsysnet/socket.h>
|
|
||||||
#include <utils/logger.h>
|
|
||||||
|
|
||||||
WUPS_PLUGIN_NAME("SwipSwapMe");
|
WUPS_PLUGIN_NAME("SwipSwapMe");
|
||||||
WUPS_PLUGIN_DESCRIPTION("Swaps the gamepad and tv screen when pressing a certain button (TV is default)");
|
WUPS_PLUGIN_DESCRIPTION("Swaps the GamePad and TV screen when pressing a certain button combination");
|
||||||
WUPS_PLUGIN_VERSION("v1.0");
|
WUPS_PLUGIN_VERSION(PLUGIN_VERSION_FULL);
|
||||||
WUPS_PLUGIN_AUTHOR("Maschell");
|
WUPS_PLUGIN_AUTHOR("Maschell");
|
||||||
WUPS_PLUGIN_LICENSE("GPL");
|
WUPS_PLUGIN_LICENSE("GPL");
|
||||||
|
|
||||||
WUPS_FS_ACCESS()
|
// FS Access
|
||||||
|
WUPS_USE_WUT_DEVOPTAB();
|
||||||
|
|
||||||
uint32_t SplashScreen(int32_t time,int32_t combotime);
|
WUPS_USE_STORAGE("SwipSwapMeAroma");
|
||||||
|
|
||||||
/* Entry point */
|
|
||||||
ON_APPLICATION_START(args) {
|
|
||||||
memset(gVoiceInfos,0,sizeof(gVoiceInfos));
|
|
||||||
socket_lib_init();
|
|
||||||
log_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
ON_APP_STATUS_CHANGED(status) {
|
|
||||||
gAppStatus = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Gets called once the loader exists.
|
||||||
INITIALIZE_PLUGIN() {
|
INITIALIZE_PLUGIN() {
|
||||||
uint32_t res = SplashScreen(10,2);
|
initLogging();
|
||||||
gButtonCombo = res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define FPS 60
|
if (NotificationModule_InitLibrary() == NOTIFICATION_MODULE_RESULT_SUCCESS) {
|
||||||
uint32_t SplashScreen(int32_t time,int32_t combotime) {
|
gNotificationModuleInitDone = true;
|
||||||
uint32_t result = VPAD_BUTTON_TV;
|
|
||||||
|
|
||||||
// Init screen
|
|
||||||
OSScreenInit();
|
|
||||||
|
|
||||||
uint32_t screen_buf0_size = OSScreenGetBufferSizeEx(SCREEN_TV);
|
|
||||||
uint32_t screen_buf1_size = OSScreenGetBufferSizeEx(SCREEN_DRC);
|
|
||||||
|
|
||||||
uint32_t * screenbuffer0 = (uint32_t*)memalign(0x100, screen_buf0_size);
|
|
||||||
uint32_t * screenbuffer1 = (uint32_t*)memalign(0x100, screen_buf1_size);
|
|
||||||
|
|
||||||
if(screenbuffer0 == NULL || screenbuffer1 == NULL) {
|
|
||||||
if(screenbuffer0 != NULL) {
|
|
||||||
free(screenbuffer0);
|
|
||||||
}
|
|
||||||
if(screenbuffer1 != NULL) {
|
|
||||||
free(screenbuffer1);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSScreenSetBufferEx(SCREEN_TV, (void *)screenbuffer0);
|
|
||||||
OSScreenSetBufferEx(SCREEN_DRC, (void *)screenbuffer1);
|
|
||||||
|
|
||||||
OSScreenEnableEx(SCREEN_TV, 1);
|
|
||||||
OSScreenEnableEx(SCREEN_DRC, 1);
|
|
||||||
|
|
||||||
// Clear screens
|
|
||||||
OSScreenClearBufferEx(SCREEN_TV, 0);
|
|
||||||
OSScreenClearBufferEx(SCREEN_DRC, 0);
|
|
||||||
|
|
||||||
// Flip buffers
|
|
||||||
OSScreenFlipBuffersEx(SCREEN_TV);
|
|
||||||
OSScreenFlipBuffersEx(SCREEN_DRC);
|
|
||||||
|
|
||||||
OSScreenClearBufferEx(SCREEN_TV, 0);
|
|
||||||
OSScreenClearBufferEx(SCREEN_DRC, 0);
|
|
||||||
|
|
||||||
std::vector<std::string> strings;
|
|
||||||
strings.push_back("SwipSwapMe 0.2 - by Maschell.");
|
|
||||||
strings.push_back("");
|
|
||||||
strings.push_back("");
|
|
||||||
strings.push_back("Press the combo you want to use for swapping now for 2 seconds.");
|
|
||||||
strings.push_back("Pressing the TV button will return directly.");
|
|
||||||
strings.push_back("");
|
|
||||||
strings.push_back("Otherwise the default combo (TV button) will be used in 10 seconds.");
|
|
||||||
uint8_t pos = 0;
|
|
||||||
for (std::vector<std::string>::iterator it = strings.begin() ; it != strings.end(); ++it) {
|
|
||||||
OSScreenPutFontEx(SCREEN_TV, 0, pos, (*it).c_str());
|
|
||||||
OSScreenPutFontEx(SCREEN_DRC, 0, pos, (*it).c_str());
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
|
|
||||||
OSScreenFlipBuffersEx(SCREEN_TV);
|
|
||||||
OSScreenFlipBuffersEx(SCREEN_DRC);
|
|
||||||
|
|
||||||
int32_t tickswait = time * FPS * 16;
|
|
||||||
|
|
||||||
int32_t sleepingtime = 16;
|
|
||||||
int32_t times = tickswait/16;
|
|
||||||
int32_t i=0;
|
|
||||||
|
|
||||||
VPADStatus vpad_data;
|
|
||||||
VPADReadError error;
|
|
||||||
uint32_t last = 0xFFFFFFFF;
|
|
||||||
int32_t timer = 0;
|
|
||||||
while(i<times) {
|
|
||||||
VPADRead(VPAD_CHAN_0, &vpad_data, 1, &error);
|
|
||||||
if(vpad_data.trigger == VPAD_BUTTON_TV)
|
|
||||||
break;
|
|
||||||
if(last == vpad_data.hold && last != 0) {
|
|
||||||
timer++;
|
|
||||||
} else {
|
} else {
|
||||||
last = vpad_data.hold;
|
gNotificationModuleInitDone = false;
|
||||||
timer = 0;
|
DEBUG_FUNCTION_LINE_ERR("Failed to init notification lib");
|
||||||
}
|
|
||||||
if(timer >= combotime*FPS) {
|
|
||||||
result = vpad_data.hold;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
OSSleepTicks(OSMicrosecondsToTicks(sleepingtime*1000));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(screenbuffer0 != NULL) {
|
// Open storage to read values
|
||||||
free(screenbuffer0);
|
WUPSStorageError storageRes = WUPS_OpenStorage();
|
||||||
}
|
if (storageRes != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
if(screenbuffer1 != NULL) {
|
DEBUG_FUNCTION_LINE_ERR("Failed to open storage %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes);
|
||||||
free(screenbuffer1);
|
} else {
|
||||||
}
|
LOAD_BOOL_FROM_STORAGE(ENABLED_CONFIG_STRING, gEnabled);
|
||||||
|
LOAD_BOOL_FROM_STORAGE(SWAP_SCREENS_CONFIG_STRING, gDoScreenSwap);
|
||||||
|
LOAD_BOOL_FROM_STORAGE(ENABLED_SWAP_SCREENS_COMBO_CONFIG_STRING, gSwapScreenButtonComboEnabled);
|
||||||
|
LOAD_BOOL_FROM_STORAGE(ENABLED_CHANGE_AUDIO_COMBO_CONFIG_STRING, gChangeAudioModeButtonComboEnabled);
|
||||||
|
LOAD_BOOL_FROM_STORAGE(ENABLE_NOTIFICATIONS_CONFIG_STRING, gShowNotifications);
|
||||||
|
LOAD_INT_FROM_STORAGE(SWAP_SCREEN_BUTTON_COMBO_CONFIG_STRING, gSwapScreenButtonCombo);
|
||||||
|
LOAD_INT_FROM_STORAGE(CHANGE_AUDIO_BUTTON_COMBO_CONFIG_STRING, gSwapAudioButtonCombo);
|
||||||
|
LOAD_INT_FROM_STORAGE(SCREEN_MODE_CONFIG_STRING, gCurAudioMode);
|
||||||
|
|
||||||
return result;
|
// Close storage
|
||||||
|
if (WUPS_CloseStorage() != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to close storage");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deinitLogging();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called whenever an application was started.
|
||||||
|
ON_APPLICATION_START() {
|
||||||
|
initLogging();
|
||||||
|
}
|
||||||
|
|
||||||
|
ON_APPLICATION_REQUESTS_EXIT() {
|
||||||
|
// Open storage to write current config
|
||||||
|
WUPSStorageError storageRes = WUPS_OpenStorage();
|
||||||
|
if (storageRes != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to open storage %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes);
|
||||||
|
} else {
|
||||||
|
WUPS_StoreInt(nullptr, SCREEN_MODE_CONFIG_STRING, (int32_t) gCurAudioMode);
|
||||||
|
WUPS_StoreBool(nullptr, SWAP_SCREENS_CONFIG_STRING, (int32_t) gDoScreenSwap);
|
||||||
|
|
||||||
|
// Close storage
|
||||||
|
if (WUPS_CloseStorage() != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to close storage");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deinitLogging();
|
||||||
|
}
|
||||||
|
|
||||||
|
ON_APPLICATION_ENDS() {
|
||||||
|
if (gNotificationModuleInitDone) {
|
||||||
|
NotificationModule_DeInitLibrary();
|
||||||
|
gNotificationModuleInitDone = false;
|
||||||
|
}
|
||||||
}
|
}
|
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
|
12
src/retain_vars.cpp
Normal file
12
src/retain_vars.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "retain_vars.hpp"
|
||||||
|
#include <vpad/input.h>
|
||||||
|
|
||||||
|
uint32_t gSwapScreenButtonCombo = VPAD_BUTTON_TV;
|
||||||
|
uint32_t gSwapAudioButtonCombo = VPAD_BUTTON_STICK_L;
|
||||||
|
bool gSwapScreenButtonComboEnabled = true;
|
||||||
|
bool gChangeAudioModeButtonComboEnabled = false;
|
||||||
|
bool gEnabled = true;
|
||||||
|
bool gDoScreenSwap = false;
|
||||||
|
bool gShowNotifications = true;
|
||||||
|
bool gNotificationModuleInitDone = true;
|
||||||
|
SwipSwapAudioMode gCurAudioMode = AUDIO_MODE_MATCH_SCREEN;
|
22
src/retain_vars.hpp
Normal file
22
src/retain_vars.hpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
typedef enum SwipSwapAudioMode {
|
||||||
|
AUDIO_MODE_NONE = 0,
|
||||||
|
AUDIO_MODE_SWAP = 1,
|
||||||
|
AUDIO_MODE_MATCH_SCREEN = 2,
|
||||||
|
AUDIO_MODE_COMBINE = 3,
|
||||||
|
AUDIO_MODE_LEFT_TV_RIGHT_DRC = 4,
|
||||||
|
AUDIO_MODE_MAX_VALUE = 5
|
||||||
|
} SwipSwapAudioMode;
|
||||||
|
|
||||||
|
extern uint32_t gSwapScreenButtonCombo;
|
||||||
|
extern uint32_t gSwapAudioButtonCombo;
|
||||||
|
extern bool gSwapScreenButtonComboEnabled;
|
||||||
|
extern bool gChangeAudioModeButtonComboEnabled;
|
||||||
|
extern bool gEnabled;
|
||||||
|
extern bool gDoScreenSwap;
|
||||||
|
extern bool gShowNotifications;
|
||||||
|
extern bool gNotificationModuleInitDone;
|
||||||
|
extern SwipSwapAudioMode gCurAudioMode;
|
265
src/utils/WUPSConfigItemButtonCombo.cpp
Normal file
265
src/utils/WUPSConfigItemButtonCombo.cpp
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
#include "WUPSConfigItemButtonCombo.h"
|
||||||
|
#include "utils/input.h"
|
||||||
|
#include <coreinit/debug.h>
|
||||||
|
#include <coreinit/thread.h>
|
||||||
|
#include <coreinit/time.h>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <vpad/input.h>
|
||||||
|
#include <wups.h>
|
||||||
|
|
||||||
|
const char *getButtonChar(VPADButtons value) {
|
||||||
|
std::string combo;
|
||||||
|
if (value & VPAD_BUTTON_A) {
|
||||||
|
return "\ue000";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_B) {
|
||||||
|
return "\ue001";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_X) {
|
||||||
|
return "\ue002";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_Y) {
|
||||||
|
return "\ue003";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_L) {
|
||||||
|
return "\ue083";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_R) {
|
||||||
|
return "\ue084";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_ZL) {
|
||||||
|
return "\ue085";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_ZR) {
|
||||||
|
return "\ue086";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_UP) {
|
||||||
|
return "\ue079";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_DOWN) {
|
||||||
|
return "\ue07A";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_LEFT) {
|
||||||
|
return "\ue07B";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_RIGHT) {
|
||||||
|
return "\ue07C";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_STICK_L) {
|
||||||
|
return "\ue081";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_STICK_R) {
|
||||||
|
return "\ue082";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_PLUS) {
|
||||||
|
return "\ue045";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_MINUS) {
|
||||||
|
return "\ue046";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_TV) {
|
||||||
|
return "\ue089";
|
||||||
|
}
|
||||||
|
if (value & VPAD_BUTTON_RESERVED_BIT) {
|
||||||
|
return "\ue01E";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getComboAsString(uint32_t value) {
|
||||||
|
char comboString[60];
|
||||||
|
memset(comboString, 0, sizeof(comboString));
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < 32; i++) {
|
||||||
|
uint32_t bitMask = 1 << i;
|
||||||
|
if (value & bitMask) {
|
||||||
|
auto val = getButtonChar(static_cast<VPADButtons>(bitMask));
|
||||||
|
if (val[0] != '\0') {
|
||||||
|
strcat(comboString, val);
|
||||||
|
strcat(comboString, "+");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string res(comboString);
|
||||||
|
if (res.ends_with("+")) {
|
||||||
|
res.pop_back();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t WUPSConfigItemButtonCombo_getCurrentValueDisplay(void *context, char *out_buf, int32_t out_size) {
|
||||||
|
auto *item = (ConfigItemButtonCombo *) context;
|
||||||
|
snprintf(out_buf, out_size, "%s", getComboAsString(item->value).c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WUPSConfigItemButtonCombo_callCallback(void *context) {
|
||||||
|
auto *item = (ConfigItemButtonCombo *) context;
|
||||||
|
if (item->callback != nullptr) {
|
||||||
|
((ButtonComboValueChangedCallback) (item->callback))(item, item->value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkForHold(ConfigItemButtonCombo *item) {
|
||||||
|
uint32_t lastHold = 0;
|
||||||
|
uint32_t holdFor = 0;
|
||||||
|
uint32_t holdForTarget = item->holdDurationInMs >> 4;
|
||||||
|
uint32_t holdAbortTarget = item->abortButtonHoldDurationInMs >> 4;
|
||||||
|
|
||||||
|
auto mask = VPAD_BUTTON_A | VPAD_BUTTON_B | VPAD_BUTTON_X | VPAD_BUTTON_Y | VPAD_BUTTON_L | VPAD_BUTTON_R |
|
||||||
|
VPAD_BUTTON_ZL | VPAD_BUTTON_ZR | VPAD_BUTTON_UP | VPAD_BUTTON_DOWN | VPAD_BUTTON_LEFT | VPAD_BUTTON_RIGHT |
|
||||||
|
VPAD_BUTTON_STICK_L | VPAD_BUTTON_STICK_R | VPAD_BUTTON_PLUS | VPAD_BUTTON_MINUS | VPAD_BUTTON_TV | VPAD_BUTTON_RESERVED_BIT;
|
||||||
|
|
||||||
|
KPADStatus kpad_data{};
|
||||||
|
KPADError kpad_error;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
uint32_t buttonsHold = 0;
|
||||||
|
VPADReadError vpad_error = VPAD_READ_UNINITIALIZED;
|
||||||
|
VPADStatus vpad_data;
|
||||||
|
VPADRead(VPAD_CHAN_0, &vpad_data, 1, &vpad_error);
|
||||||
|
if (vpad_error == VPAD_READ_SUCCESS) {
|
||||||
|
buttonsHold = vpad_data.hold;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
memset(&kpad_data, 0, sizeof(kpad_data));
|
||||||
|
if (KPADReadEx((KPADChan) i, &kpad_data, 1, &kpad_error) > 0) {
|
||||||
|
if (kpad_error == KPAD_ERROR_OK && kpad_data.extensionType != 0xFF) {
|
||||||
|
if (kpad_data.extensionType == WPAD_EXT_CORE || kpad_data.extensionType == WPAD_EXT_NUNCHUK) {
|
||||||
|
buttonsHold |= remapWiiMoteButtons(kpad_data.hold);
|
||||||
|
} else if (kpad_data.extensionType == WPAD_EXT_PRO_CONTROLLER) {
|
||||||
|
buttonsHold |= remapProButtons(kpad_data.pro.hold);
|
||||||
|
} else {
|
||||||
|
buttonsHold |= remapClassicButtons(kpad_data.classic.hold);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonsHold &= mask;
|
||||||
|
|
||||||
|
if (buttonsHold == lastHold) {
|
||||||
|
if (buttonsHold != 0) {
|
||||||
|
holdFor++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
holdFor = 0;
|
||||||
|
}
|
||||||
|
lastHold = buttonsHold;
|
||||||
|
|
||||||
|
if (holdFor >= holdAbortTarget && lastHold == item->abortButton) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (holdFor >= holdForTarget) {
|
||||||
|
item->value = lastHold;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
OSSleepTicks(OSMillisecondsToTicks(16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WUPSConfigItemButtonCombo_onButtonPressed(void *context, WUPSConfigButtons buttons) {
|
||||||
|
auto *item = (ConfigItemButtonCombo *) context;
|
||||||
|
if (item->state == BUTTON_COMBO_STATE_NONE) {
|
||||||
|
if ((buttons & WUPS_CONFIG_BUTTON_A) == WUPS_CONFIG_BUTTON_A) {
|
||||||
|
item->state = BUTTON_COMBO_STATE_PREPARE_FOR_HOLD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WUPSConfigItemButtonCombo_isMovementAllowed(void *context) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t WUPSConfigItemButtonCombo_getCurrentValueSelectedDisplay(void *context, char *out_buf, int32_t out_size) {
|
||||||
|
auto *item = (ConfigItemButtonCombo *) context;
|
||||||
|
if (item->state == BUTTON_COMBO_STATE_PREPARE_FOR_HOLD || item->state == BUTTON_COMBO_STATE_WAIT_FOR_HOLD) {
|
||||||
|
if (item->state == BUTTON_COMBO_STATE_PREPARE_FOR_HOLD) {
|
||||||
|
item->state = BUTTON_COMBO_STATE_WAIT_FOR_HOLD;
|
||||||
|
snprintf(out_buf, out_size, "<Hold new combo for %dms; hold %s to abort>", item->holdDurationInMs, getButtonChar(item->abortButton));
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
checkForHold(item);
|
||||||
|
item->state = BUTTON_COMBO_STATE_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snprintf(out_buf, out_size, "(Press \ue000 to change) %s", getComboAsString(item->value).c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WUPSConfigItemButtonCombo_restoreDefault(void *context) {
|
||||||
|
auto *item = (ConfigItemButtonCombo *) context;
|
||||||
|
item->value = item->defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WUPSConfigItemButtonCombo_onSelected(void *context, bool isSelected) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void WUPSConfigItemButtonCombo_onDelete(void *context) {
|
||||||
|
auto *item = (ConfigItemButtonCombo *) context;
|
||||||
|
if (item->configId) {
|
||||||
|
free(item->configId);
|
||||||
|
}
|
||||||
|
free(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" bool
|
||||||
|
WUPSConfigItemButtonComboAddToCategoryEx(WUPSConfigCategoryHandle cat, const char *configID, const char *displayName, uint32_t defaultComboInVPADButtons, uint32_t holdDurationInMs, VPADButtons abortButton, uint32_t abortButtonHoldDurationInMs, ButtonComboValueChangedCallback callback) {
|
||||||
|
if (cat == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto *item = (ConfigItemButtonCombo *) malloc(sizeof(ConfigItemButtonCombo));
|
||||||
|
if (item == nullptr) {
|
||||||
|
OSReport("WUPSConfigItemButtonComboAddToCategoryEx: Failed to allocate memory for item data.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configID != nullptr) {
|
||||||
|
item->configId = strdup(configID);
|
||||||
|
} else {
|
||||||
|
item->configId = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
item->abortButton = abortButton;
|
||||||
|
item->abortButtonHoldDurationInMs = abortButtonHoldDurationInMs;
|
||||||
|
item->holdDurationInMs = holdDurationInMs;
|
||||||
|
item->defaultValue = defaultComboInVPADButtons;
|
||||||
|
item->value = defaultComboInVPADButtons;
|
||||||
|
item->callback = (void *) callback;
|
||||||
|
item->state = BUTTON_COMBO_STATE_NONE;
|
||||||
|
|
||||||
|
WUPSConfigCallbacks_t callbacks = {
|
||||||
|
.getCurrentValueDisplay = &WUPSConfigItemButtonCombo_getCurrentValueDisplay,
|
||||||
|
.getCurrentValueSelectedDisplay = &WUPSConfigItemButtonCombo_getCurrentValueSelectedDisplay,
|
||||||
|
.onSelected = &WUPSConfigItemButtonCombo_onSelected,
|
||||||
|
.restoreDefault = &WUPSConfigItemButtonCombo_restoreDefault,
|
||||||
|
.isMovementAllowed = &WUPSConfigItemButtonCombo_isMovementAllowed,
|
||||||
|
.callCallback = &WUPSConfigItemButtonCombo_callCallback,
|
||||||
|
.onButtonPressed = &WUPSConfigItemButtonCombo_onButtonPressed,
|
||||||
|
.onDelete = &WUPSConfigItemButtonCombo_onDelete};
|
||||||
|
|
||||||
|
if (WUPSConfigItem_Create(&item->handle, configID, displayName, callbacks, item) < 0) {
|
||||||
|
OSReport("WUPSConfigItemButtonComboAddToCategoryEx: Failed to create config item.\n");
|
||||||
|
free(item);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WUPSConfigCategory_AddItem(cat, item->handle) < 0) {
|
||||||
|
OSReport("WUPSConfigItemButtonComboAddToCategoryEx: Failed to add item to category.\n");
|
||||||
|
WUPSConfigItem_Destroy(item->handle);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" bool
|
||||||
|
WUPSConfigItemButtonComboAddToCategory(WUPSConfigCategoryHandle cat, const char *configID, const char *displayName, uint32_t defaultComboInVPADButtons, ButtonComboValueChangedCallback callback) {
|
||||||
|
return WUPSConfigItemButtonComboAddToCategoryEx(cat, configID, displayName, defaultComboInVPADButtons, 2000, VPAD_BUTTON_B, 250, callback);
|
||||||
|
}
|
43
src/utils/WUPSConfigItemButtonCombo.h
Normal file
43
src/utils/WUPSConfigItemButtonCombo.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <vpad/input.h>
|
||||||
|
#include <wups.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum ButtonComboState {
|
||||||
|
BUTTON_COMBO_STATE_NONE,
|
||||||
|
BUTTON_COMBO_STATE_PREPARE_FOR_HOLD,
|
||||||
|
BUTTON_COMBO_STATE_WAIT_FOR_HOLD,
|
||||||
|
} ButtonComboState;
|
||||||
|
|
||||||
|
typedef struct ConfigItemButtonCombo {
|
||||||
|
char *configId;
|
||||||
|
WUPSConfigItemHandle handle;
|
||||||
|
uint32_t defaultValue;
|
||||||
|
uint32_t value;
|
||||||
|
uint32_t holdDurationInMs;
|
||||||
|
VPADButtons abortButton;
|
||||||
|
uint32_t abortButtonHoldDurationInMs;
|
||||||
|
void *callback;
|
||||||
|
ButtonComboState state;
|
||||||
|
} ConfigItemButtonCombo;
|
||||||
|
|
||||||
|
typedef void (*ButtonComboValueChangedCallback)(ConfigItemButtonCombo *item, uint32_t buttonComboInVPADButtons);
|
||||||
|
|
||||||
|
bool WUPSConfigItemButtonComboAddToCategory(WUPSConfigCategoryHandle cat, const char *configId, const char *displayName, uint32_t defaultComboInVPADButtons, ButtonComboValueChangedCallback callback);
|
||||||
|
|
||||||
|
bool WUPSConfigItemButtonComboAddToCategoryEx(WUPSConfigCategoryHandle cat, const char *configId, const char *displayName, uint32_t defaultComboInVPADButtons, uint32_t holdDurationInMs, VPADButtons abortButton, uint32_t abortButtonHoldDurationInMs, ButtonComboValueChangedCallback callback);
|
||||||
|
|
||||||
|
#define WUPSConfigItemButtonCombo_AddToCategoryHandled(__config__, __cat__, __configID__, __displayName__, __defaultComboInVPADButtons__, __callback__) \
|
||||||
|
do { \
|
||||||
|
if (!WUPSConfigItemButtonComboAddToCategory(__cat__, __configID__, __displayName__, __defaultComboInVPADButtons__, __callback__)) { \
|
||||||
|
WUPSConfig_Destroy(__config__); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
104
src/utils/config.cpp
Normal file
104
src/utils/config.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#include "config.h"
|
||||||
|
#include "WUPSConfigItemButtonCombo.h"
|
||||||
|
#include "retain_vars.hpp"
|
||||||
|
#include <map>
|
||||||
|
#include <wups/config/WUPSConfigItemMultipleValues.h>
|
||||||
|
extern void UpdateAudioMode();
|
||||||
|
|
||||||
|
void boolItemChangedConfig(ConfigItemBoolean *item, bool newValue) {
|
||||||
|
if (std::string_view(item->configId) == ENABLED_CONFIG_STRING) {
|
||||||
|
DEBUG_FUNCTION_LINE("New value in %s: %d", ENABLED_CONFIG_STRING, newValue);
|
||||||
|
gEnabled = newValue;
|
||||||
|
WUPS_StoreInt(nullptr, ENABLED_CONFIG_STRING, gEnabled);
|
||||||
|
UpdateAudioMode();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PROCESS_BOOL_ITEM_CHANGED(SWAP_SCREENS_CONFIG_STRING, gDoScreenSwap);
|
||||||
|
PROCESS_BOOL_ITEM_CHANGED(ENABLED_SWAP_SCREENS_COMBO_CONFIG_STRING, gSwapScreenButtonComboEnabled);
|
||||||
|
PROCESS_BOOL_ITEM_CHANGED(ENABLED_CHANGE_AUDIO_COMBO_CONFIG_STRING, gChangeAudioModeButtonComboEnabled);
|
||||||
|
PROCESS_BOOL_ITEM_CHANGED(ENABLE_NOTIFICATIONS_CONFIG_STRING, gShowNotifications);
|
||||||
|
}
|
||||||
|
|
||||||
|
void buttonComboItemChanged(ConfigItemButtonCombo *item, uint32_t newValue) {
|
||||||
|
if (item && item->configId) {
|
||||||
|
if (std::string_view(item->configId) == SWAP_SCREEN_BUTTON_COMBO_CONFIG_STRING) {
|
||||||
|
gSwapScreenButtonCombo = newValue;
|
||||||
|
WUPS_StoreInt(nullptr, item->configId, (int32_t) gSwapScreenButtonCombo);
|
||||||
|
} else if (std::string_view(item->configId) == CHANGE_AUDIO_BUTTON_COMBO_CONFIG_STRING) {
|
||||||
|
gSwapAudioButtonCombo = newValue;
|
||||||
|
WUPS_StoreInt(nullptr, item->configId, (int32_t) gSwapAudioButtonCombo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void getConfigInfoForMap(std::map<SwipSwapAudioMode, const char *> &curMap, ConfigItemMultipleValuesPair *pair, uint32_t default_lang, uint32_t *default_index, uint32_t *len) {
|
||||||
|
uint32_t i = 0;
|
||||||
|
for (auto &curEntry : curMap) {
|
||||||
|
if (default_lang == curEntry.first) {
|
||||||
|
*default_index = i;
|
||||||
|
}
|
||||||
|
pair[i].value = curEntry.first;
|
||||||
|
pair[i].valueName = (char *) curEntry.second;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
*len = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void default_lang_changed(ConfigItemMultipleValues *item, uint32_t newValue) {
|
||||||
|
DEBUG_FUNCTION_LINE("New value in %s changed: %d", item->configId, newValue);
|
||||||
|
|
||||||
|
if (strcmp(item->configId, SCREEN_MODE_CONFIG_STRING) == 0) {
|
||||||
|
gCurAudioMode = static_cast<SwipSwapAudioMode>(newValue);
|
||||||
|
WUPS_StoreInt(nullptr, item->configId, (int32_t) gCurAudioMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_ERR("Failed to open storage");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WUPSConfigHandle config;
|
||||||
|
WUPSConfig_CreateHandled(&config, "SwipSwapMe");
|
||||||
|
|
||||||
|
WUPSConfigCategoryHandle setting;
|
||||||
|
WUPSConfig_AddCategoryByNameHandled(config, "Settings", &setting);
|
||||||
|
WUPSConfigCategoryHandle combos;
|
||||||
|
WUPSConfig_AddCategoryByNameHandled(config, "Button combos", &combos);
|
||||||
|
|
||||||
|
std::map<SwipSwapAudioMode, const char *> audioModeMap{
|
||||||
|
{AUDIO_MODE_NONE, "Normal"},
|
||||||
|
{AUDIO_MODE_SWAP, "Swap TV and GamePad sound"},
|
||||||
|
{AUDIO_MODE_MATCH_SCREEN, "Sound matches screen"},
|
||||||
|
{AUDIO_MODE_COMBINE, "Combine TV and GamePad sound"},
|
||||||
|
{AUDIO_MODE_LEFT_TV_RIGHT_DRC, "Left: TV; Right: GamePad"}};
|
||||||
|
|
||||||
|
ConfigItemMultipleValuesPair audioModePairs[audioModeMap.size()];
|
||||||
|
|
||||||
|
uint32_t number_values = 0;
|
||||||
|
uint32_t default_index = 0;
|
||||||
|
getConfigInfoForMap(audioModeMap, audioModePairs, gCurAudioMode, &default_index, &number_values);
|
||||||
|
|
||||||
|
WUPSConfigItemBoolean_AddToCategoryHandled(config, setting, ENABLED_CONFIG_STRING, "Plugin enabled", gEnabled, &boolItemChangedConfig);
|
||||||
|
WUPSConfigItemBoolean_AddToCategoryHandled(config, setting, ENABLE_NOTIFICATIONS_CONFIG_STRING, "Show notifications", gShowNotifications, &boolItemChangedConfig);
|
||||||
|
WUPSConfigItemBoolean_AddToCategoryHandled(config, setting, SWAP_SCREENS_CONFIG_STRING, "Swap screens", gDoScreenSwap, &boolItemChangedConfig);
|
||||||
|
WUPSConfigItemMultipleValues_AddToCategoryHandled(config, setting, SCREEN_MODE_CONFIG_STRING, "Audio mode:", default_index, audioModePairs, number_values,
|
||||||
|
&default_lang_changed);
|
||||||
|
|
||||||
|
WUPSConfigItemBoolean_AddToCategoryHandled(config, combos, ENABLED_SWAP_SCREENS_COMBO_CONFIG_STRING, "Enable swap screen button combo", gSwapScreenButtonComboEnabled, &boolItemChangedConfig);
|
||||||
|
WUPSConfigItemButtonCombo_AddToCategoryHandled(config, combos, SWAP_SCREEN_BUTTON_COMBO_CONFIG_STRING, "Swap screen", gSwapScreenButtonCombo, &buttonComboItemChanged);
|
||||||
|
WUPSConfigItemBoolean_AddToCategoryHandled(config, combos, ENABLED_CHANGE_AUDIO_COMBO_CONFIG_STRING, "Enable change audio mode button combo", gChangeAudioModeButtonComboEnabled, &boolItemChangedConfig);
|
||||||
|
WUPSConfigItemButtonCombo_AddToCategoryHandled(config, combos, CHANGE_AUDIO_BUTTON_COMBO_CONFIG_STRING, "Change audio", gSwapAudioButtonCombo, &buttonComboItemChanged);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
WUPS_CONFIG_CLOSED() {
|
||||||
|
// Save all changes
|
||||||
|
if (WUPS_CloseStorage() != WUPS_STORAGE_ERROR_SUCCESS) {
|
||||||
|
DEBUG_FUNCTION_LINE_ERR("Failed to close storage");
|
||||||
|
}
|
||||||
|
}
|
53
src/utils/config.h
Normal file
53
src/utils/config.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "logger.h"
|
||||||
|
#include <string>
|
||||||
|
#include <wups/config/WUPSConfigItemBoolean.h>
|
||||||
|
#include <wups/storage.h>
|
||||||
|
|
||||||
|
#define ENABLED_CONFIG_STRING "enabled"
|
||||||
|
#define SWAP_SCREENS_CONFIG_STRING "swapScreens"
|
||||||
|
#define ENABLED_SWAP_SCREENS_COMBO_CONFIG_STRING "swapScreensComboEnabled"
|
||||||
|
#define ENABLED_CHANGE_AUDIO_COMBO_CONFIG_STRING "changeAudioComboEnabled"
|
||||||
|
#define ENABLE_NOTIFICATIONS_CONFIG_STRING "notificationsEnabled"
|
||||||
|
#define SWAP_SCREEN_BUTTON_COMBO_CONFIG_STRING "screenButtonCombo"
|
||||||
|
#define CHANGE_AUDIO_BUTTON_COMBO_CONFIG_STRING "audioButtonCombo"
|
||||||
|
#define SCREEN_MODE_CONFIG_STRING "audioMode"
|
||||||
|
|
||||||
|
#define LOAD_BOOL_FROM_STORAGE(config_name, __variable__) \
|
||||||
|
if ((storageRes = WUPS_GetBool(nullptr, config_name, &__variable__)) == WUPS_STORAGE_ERROR_NOT_FOUND) { \
|
||||||
|
if (WUPS_StoreBool(nullptr, 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(config_name, __string, __string_length) \
|
||||||
|
if ((storageRes = WUPS_GetString(nullptr, config_name, __string, __string_length)) == WUPS_STORAGE_ERROR_NOT_FOUND) { \
|
||||||
|
if (WUPS_StoreString(nullptr, 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 LOAD_INT_FROM_STORAGE(config_name, __intValue) \
|
||||||
|
if ((storageRes = WUPS_GetInt(nullptr, config_name, (int32_t *) &__intValue)) == WUPS_STORAGE_ERROR_NOT_FOUND) { \
|
||||||
|
if (WUPS_StoreInt(nullptr, config_name, (int32_t) __intValue) != WUPS_STORAGE_ERROR_SUCCESS) { \
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("Failed to store int"); \
|
||||||
|
} \
|
||||||
|
} else if (storageRes != WUPS_STORAGE_ERROR_SUCCESS) { \
|
||||||
|
DEBUG_FUNCTION_LINE_WARN("Failed to get int %s (%d)", WUPS_GetStorageStatusStr(storageRes), storageRes); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
#define PROCESS_BOOL_ITEM_CHANGED(__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(nullptr, __config__name, __variable__); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
while (0)
|
187
src/utils/input.cpp
Normal file
187
src/utils/input.cpp
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
#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;
|
||||||
|
}
|
||||||
|
if (buttons & WPAD_PRO_RESERVED) {
|
||||||
|
conv_buttons |= VPAD_BUTTON_RESERVED_BIT;
|
||||||
|
}
|
||||||
|
return conv_buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkButtonComboVPAD(VPADStatus *buffer, uint32_t buffer_size, uint32_t buttonCombo, uint32_t &wasHoldForXFrames) {
|
||||||
|
bool result = false;
|
||||||
|
bool wasPressed = false;
|
||||||
|
for (uint32_t i = 0; i < buffer_size; i++) {
|
||||||
|
if ((((buffer[i].hold & 0x000FFFFF) & buttonCombo) == buttonCombo)) {
|
||||||
|
wasPressed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wasPressed) {
|
||||||
|
if (wasHoldForXFrames == 0) {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
wasHoldForXFrames++;
|
||||||
|
} else {
|
||||||
|
wasHoldForXFrames = 0;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkButtonComboWPAD(uint32_t buttonHold, uint32_t buttonCombo, uint32_t &wasHoldForXFrames) {
|
||||||
|
auto result = false;
|
||||||
|
if (((buttonHold & 0x000FFFFF) & buttonCombo) == buttonCombo) {
|
||||||
|
if (wasHoldForXFrames == 0) {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
wasHoldForXFrames++;
|
||||||
|
} else {
|
||||||
|
wasHoldForXFrames = 0;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
14
src/utils/input.h
Normal file
14
src/utils/input.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <padscore/kpad.h>
|
||||||
|
#include <vpad/input.h>
|
||||||
|
|
||||||
|
#define VPAD_BUTTON_RESERVED_BIT 0x80000
|
||||||
|
|
||||||
|
uint32_t remapWiiMoteButtons(uint32_t buttons);
|
||||||
|
uint32_t remapClassicButtons(uint32_t buttons);
|
||||||
|
uint32_t remapProButtons(uint32_t buttons);
|
||||||
|
|
||||||
|
bool checkButtonComboVPAD(VPADStatus *buffer, uint32_t buffer_size, uint32_t buttonCombo, uint32_t &wasHoldForXFrames);
|
||||||
|
bool checkButtonComboWPAD(uint32_t vpadButtonHold, uint32_t vpadButtonCombo, uint32_t &wasHoldForXFrames);
|
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
|
||||||
|
}
|
68
src/utils/logger.h
Normal file
68
src/utils/logger.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#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 "SwipSwapMe"
|
||||||
|
|
||||||
|
#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
|
||||||
|
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__)
|
||||||
|
|
||||||
|
#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_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_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
|
12
src/utils/utils.h
Normal file
12
src/utils/utils.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <coreinit/dynload.h>
|
||||||
|
|
||||||
|
inline bool isModuleLoaded(const char *name) {
|
||||||
|
OSDynLoad_Module module;
|
||||||
|
auto err = OSDynLoad_IsModuleLoaded(name, &module);
|
||||||
|
|
||||||
|
if (err != OS_DYNLOAD_OK || !module) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
@ -1,30 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2017,2018 Maschell
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#ifndef _VOICE_INFO_H_
|
|
||||||
#define _VOICE_INFO_H_
|
|
||||||
|
|
||||||
#define VOICE_INFO_MAX 100
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef struct _VoiceInfo {
|
|
||||||
void* voice; /**< Pointer to the voice */
|
|
||||||
uint32_t mixTV[24]; /**< Mix to the TV */
|
|
||||||
uint32_t mixDRC[24]; /**< Mix of the DRC */
|
|
||||||
} VoiceInfo;
|
|
||||||
|
|
||||||
#endif //_VOICE_INFO_H_
|
|
@ -1,65 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2017,2018 Maschell
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include <utils/logger.h>
|
|
||||||
#include "voice_info.h"
|
|
||||||
#include "voice_swapper.h"
|
|
||||||
|
|
||||||
void VoiceSwapper_acquireVoice(void * voice){
|
|
||||||
for(int32_t i = 0;i<VOICE_INFO_MAX;i++){
|
|
||||||
if(gVoiceInfos[i].voice == NULL){
|
|
||||||
if(VOICE_SWAP_LOG == 1){log_printf("[VoiceSwapper] acquireVoice in slot %d for %08X!\n",i,voice);}
|
|
||||||
gVoiceInfos[i].voice = voice;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoiceSwapper_freeVoice(void * voice){
|
|
||||||
for(int32_t i = 0;i<VOICE_INFO_MAX;i++){
|
|
||||||
if(gVoiceInfos[i].voice == voice){
|
|
||||||
if(VOICE_SWAP_LOG == 1){log_printf("[VoiceSwapper] freeVoice in slot %d for %08X!\n",i,voice);}
|
|
||||||
gVoiceInfos[i].voice = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoiceSwapper_setMix(void * voice,uint32_t device, void* mix){
|
|
||||||
for(int32_t i = 0;i<VOICE_INFO_MAX;i++){
|
|
||||||
if(gVoiceInfos[i].voice == voice){
|
|
||||||
if(VOICE_SWAP_LOG == 1){log_printf("[VoiceSwapper] setMix in slot %d for %08X!\n",i,voice);}
|
|
||||||
if(device == 0){
|
|
||||||
memcpy(gVoiceInfos[i].mixTV,mix,sizeof(gVoiceInfos[i].mixTV));
|
|
||||||
}else if(device == 1){
|
|
||||||
memcpy(gVoiceInfos[i].mixDRC,mix,sizeof(gVoiceInfos[i].mixDRC));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoiceSwapper_swapAll(){
|
|
||||||
for(int32_t i = 0;i<VOICE_INFO_MAX;i++){
|
|
||||||
if(gVoiceInfos[i].voice == NULL) continue;
|
|
||||||
if(VOICE_SWAP_LOG == 1){log_printf("[VoiceSwapper] swapping slot %d, voice %08X!\n",i,gVoiceInfos[i].voice);}
|
|
||||||
uint32_t buffer[24];
|
|
||||||
memcpy(buffer,gVoiceInfos[i].mixTV,sizeof(gVoiceInfos[i].mixTV));
|
|
||||||
memcpy(gVoiceInfos[i].mixTV,gVoiceInfos[i].mixDRC,sizeof(gVoiceInfos[i].mixTV));
|
|
||||||
memcpy(gVoiceInfos[i].mixDRC,buffer,sizeof(gVoiceInfos[i].mixTV));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
* Copyright (C) 2017,2018 Maschell
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
****************************************************************************/
|
|
||||||
#ifndef _VOICE_SWAPPER_H_
|
|
||||||
#define _VOICE_SWAPPER_H_
|
|
||||||
#define VOICE_SWAP_LOG 0
|
|
||||||
#include "voice_info.h"
|
|
||||||
#include "common/c_retain_vars.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
void VoiceSwapper_acquireVoice(void * voice);
|
|
||||||
|
|
||||||
void VoiceSwapper_freeVoice(void * voice);
|
|
||||||
|
|
||||||
void VoiceSwapper_setMix(void * voice,uint32_t device, void* mix);
|
|
||||||
|
|
||||||
void VoiceSwapper_swapAll();
|
|
||||||
|
|
||||||
#endif //_VOICE_SWAPPER_H_
|
|
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