diff --git a/.gitmodules b/.gitmodules index 5390e748..8b137891 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1 @@ -[submodule "TrainingModpackOverlay/libs/libtesla"] - path = TrainingModpackOverlay/libs/libtesla - url = https://github.com/WerWolv/libtesla diff --git a/Cargo.toml b/Cargo.toml index d4cfdf98..4d4568ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,10 +10,17 @@ crate-type = ["cdylib"] [dependencies] skyline = { git = "https://github.com/ultimate-research/skyline-rs.git" } skyline_smash = { git = "https://github.com/ultimate-research/skyline-smash.git" } +skyline-web = { git = "https://github.com/skyline-rs/skyline-web.git" } bitflags = "1.2.1" parking_lot = { version = "0.11.0", features = ["nightly"] } lazy_static = "1.4.0" owo-colors = "1.1.3" +ramhorns = "0.10.1" +paste = "1.0" +num = "0.3.0" +num-derive = "0.3" +num-traits = "0.2" +wsl = "0.1.0" [profile.dev] panic = "abort" diff --git a/TrainingModpackOverlay/.clang-format b/TrainingModpackOverlay/.clang-format deleted file mode 100644 index c5de4a70..00000000 --- a/TrainingModpackOverlay/.clang-format +++ /dev/null @@ -1,70 +0,0 @@ ---- -AccessModifierOffset: '-4' -AlignAfterOpenBracket: Align -AlignConsecutiveAssignments: 'true' -AlignConsecutiveDeclarations: 'true' -AlignEscapedNewlines: Left -AlignOperands: 'true' -AlignTrailingComments: 'true' -AllowAllParametersOfDeclarationOnNextLine: 'true' -AllowShortBlocksOnASingleLine: 'false' -AllowShortCaseLabelsOnASingleLine: 'false' -AllowShortFunctionsOnASingleLine: Inline -AllowShortIfStatementsOnASingleLine: 'true' -AllowShortLoopsOnASingleLine: 'true' -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: 'true' -AlwaysBreakTemplateDeclarations: 'false' -BinPackArguments: 'false' -BinPackParameters: 'false' -BreakBeforeBinaryOperators: NonAssignment -BreakBeforeBraces: Custom -BraceWrapping: - AfterClass: 'true' - AfterControlStatement: 'true' - AfterEnum: 'true' - AfterFunction: 'true' - AfterNamespace: 'true' - AfterStruct: 'true' - AfterUnion: 'true' - AfterExternBlock: 'true' - BeforeCatch: 'true' - BeforeElse: 'true' - SplitEmptyFunction: 'false' - SplitEmptyRecord: 'false' - SplitEmptyNamespace: 'false' -BreakBeforeTernaryOperators: 'true' -BreakConstructorInitializers: BeforeComma -BreakStringLiterals: 'false' -ColumnLimit: '128' -CompactNamespaces: 'false' -ConstructorInitializerAllOnOneLineOrOnePerLine: 'true' -Cpp11BracedListStyle: 'true' -FixNamespaceComments: 'true' -IncludeBlocks: Regroup -IndentCaseLabels: 'false' -IndentPPDirectives: AfterHash -IndentWidth: '4' -IndentWrappedFunctionNames: 'true' -KeepEmptyLinesAtTheStartOfBlocks: 'false' -Language: Cpp -MaxEmptyLinesToKeep: '1' -PointerAlignment: Left -ReflowComments: 'true' -SortIncludes: 'false' -SortUsingDeclarations: 'false' -SpaceAfterCStyleCast: 'false' -SpaceAfterTemplateKeyword: 'false' -SpaceBeforeAssignmentOperators: 'true' -SpaceBeforeParens: Never -SpaceInEmptyParentheses: 'false' -SpacesInAngles: 'false' -SpacesInCStyleCastParentheses: 'false' -SpacesInContainerLiterals: 'false' -SpacesInParentheses: 'false' -SpacesInSquareBrackets: 'false' -Standard: Cpp11 -TabWidth: '4' -UseTab: ForIndentation - -... diff --git a/TrainingModpackOverlay/.github/FUNDING.yml b/TrainingModpackOverlay/.github/FUNDING.yml deleted file mode 100644 index c5522058..00000000 --- a/TrainingModpackOverlay/.github/FUNDING.yml +++ /dev/null @@ -1,5 +0,0 @@ -# These are supported funding model platforms - -patreon: werwolv -custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KP7XRJAND9KWU&source=url -github: WerWolv diff --git a/TrainingModpackOverlay/.vscode/c_cpp_properties.json b/TrainingModpackOverlay/.vscode/c_cpp_properties.json deleted file mode 100644 index c82329be..00000000 --- a/TrainingModpackOverlay/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "configurations": [ - { - "name": "DKP Aarch64 Windows", - "includePath": [ - "C:/devkitPro/devkitA64/aarch64-none-elf/include/**", - "C:/devkitPro/devkitA64/lib/gcc/aarch64-none-elf/10.1.0/include/**", - "C:/devkitPro/libnx/include/**", - "C:/devkitPro/portlibs/switch/include/**", - "C:/devkitPro/portlibs/switch/include/freetype2/**", - "${workspaceFolder}/include/**", - "${workspaceFolder}/libs/libtesla/include/**" - ], - "defines": [ - "SWITCH", - "__SWITCH__", - "__aarch64__", - "VERSION=\"\"" - ], - "compilerPath": "C:/devkitPro/devkitA64/bin/aarch64-none-elf-g++", - "cStandard": "c11", - "cppStandard": "c++17", - "intelliSenseMode": "gcc-x64" - }, - { - "name": "DKP Aarch64 Linux", - "includePath": [ - "/opt/devkitpro/devkitA64/aarch64-none-elf/include/**", - "/opt/devkitpro/devkitA64/lib/gcc/aarch64-none-elf/8.3.0/include/**", - "/opt/devkitpro/libnx/include/**", - "/opt/devkitpro/portlibs/switch/include/**", - "/opt/devkitpro/portlibs/switch/include/**", - "/opt/devkitpro/portlibs/switch/include/freetype2/**", - "${workspaceFolder}/include/**", - "${workspaceFolder}/libs/libtesla/include/**" - ], - "defines": [ - "SWITCH", - "__SWITCH__", - "__aarch64__", - "VERSION=\"\"" - ], - "compilerPath": "/opt/devkitpro/devkitA64/bin/aarch64-none-elf-g++", - "cStandard": "c11", - "cppStandard": "c++17", - "intelliSenseMode": "gcc-x64" - } - ], - "version": 4 -} \ No newline at end of file diff --git a/TrainingModpackOverlay/.vscode/settings.json b/TrainingModpackOverlay/.vscode/settings.json deleted file mode 100644 index da837933..00000000 --- a/TrainingModpackOverlay/.vscode/settings.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "files.associations": { - "chrono": "cpp", - "string_view": "cpp", - "array": "cpp", - "atomic": "cpp", - "bit": "cpp", - "*.tcc": "cpp", - "cctype": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "string": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "initializer_list": "cpp", - "iosfwd": "cpp", - "istream": "cpp", - "limits": "cpp", - "new": "cpp", - "ostream": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "cinttypes": "cpp", - "typeinfo": "cpp", - "codecvt": "cpp", - "condition_variable": "cpp", - "iomanip": "cpp", - "mutex": "cpp", - "forward_list": "cpp", - "list": "cpp", - "map": "cpp", - "valarray": "cpp" - } -} \ No newline at end of file diff --git a/TrainingModpackOverlay/LICENSE b/TrainingModpackOverlay/LICENSE deleted file mode 100644 index d159169d..00000000 --- a/TrainingModpackOverlay/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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 2 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, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/TrainingModpackOverlay/Makefile b/TrainingModpackOverlay/Makefile deleted file mode 100644 index ba4ec9fd..00000000 --- a/TrainingModpackOverlay/Makefile +++ /dev/null @@ -1,212 +0,0 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- - -ifeq ($(strip $(DEVKITPRO)),) -$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") -endif - -TOPDIR ?= $(CURDIR) -include $(DEVKITPRO)/libnx/switch_rules - -#--------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# DATA is a list of directories containing data files -# INCLUDES is a list of directories containing header files -# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional) -# -# NO_ICON: if set to anything, do not use icon. -# NO_NACP: if set to anything, no .nacp file is generated. -# APP_TITLE is the name of the app stored in the .nacp file (Optional) -# APP_AUTHOR is the author of the app stored in the .nacp file (Optional) -# APP_VERSION is the version of the app stored in the .nacp file (Optional) -# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional) -# ICON is the filename of the icon (.jpg), relative to the project folder. -# If not set, it attempts to use one of the following (in this order): -# - .jpg -# - icon.jpg -# - /default_icon.jpg -# -# CONFIG_JSON is the filename of the NPDM config file (.json), relative to the project folder. -# If not set, it attempts to use one of the following (in this order): -# - .json -# - config.json -# If a JSON file is provided or autodetected, an ExeFS PFS0 (.nsp) is built instead -# of a homebrew executable (.nro). This is intended to be used for sysmodules. -# NACP building is skipped as well. -#--------------------------------------------------------------------------------- -APP_TITLE := Training Modpack -APP_VERSION := 2.6 - -TARGET := ovlTrainingModpack -BUILD := build -SOURCES := source -DATA := data -INCLUDES := include libs/libtesla/include - -ifeq ($(RELEASE),) - APP_VERSION := $(APP_VERSION) -endif - -NO_ICON := 1 - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- -ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE - -CFLAGS := -g -Wall -O2 -ffunction-sections \ - $(ARCH) $(DEFINES) - -CFLAGS += $(INCLUDE) -D__SWITCH__ -DVERSION=\"v$(APP_VERSION)\" - -CXXFLAGS := $(CFLAGS) -fno-exceptions -std=c++17 - -ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) - -LIBS := -lnx - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := $(PORTLIBS) $(LIBNX) - - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- - -export OUTPUT := $(CURDIR)/$(TARGET) -export TOPDIR := $(CURDIR) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -export DEPSDIR := $(CURDIR)/$(BUILD) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) -#--------------------------------------------------------------------------------- - export LD := $(CC) -#--------------------------------------------------------------------------------- -else -#--------------------------------------------------------------------------------- - export LD := $(CXX) -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- - -export OFILES_BIN := $(addsuffix .o,$(BINFILES)) -export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) -export OFILES := $(OFILES_BIN) $(OFILES_SRC) -export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) - -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) - -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) - -ifeq ($(strip $(CONFIG_JSON)),) - jsons := $(wildcard *.json) - ifneq (,$(findstring $(TARGET).json,$(jsons))) - export APP_JSON := $(TOPDIR)/$(TARGET).json - else - ifneq (,$(findstring config.json,$(jsons))) - export APP_JSON := $(TOPDIR)/config.json - endif - endif -else - export APP_JSON := $(TOPDIR)/$(CONFIG_JSON) -endif - -ifeq ($(strip $(ICON)),) - icons := $(wildcard *.jpg) - ifneq (,$(findstring $(TARGET).jpg,$(icons))) - export APP_ICON := $(TOPDIR)/$(TARGET).jpg - else - ifneq (,$(findstring icon.jpg,$(icons))) - export APP_ICON := $(TOPDIR)/icon.jpg - endif - endif -else - export APP_ICON := $(TOPDIR)/$(ICON) -endif - -ifeq ($(strip $(NO_ICON)),) - export NROFLAGS += --icon=$(APP_ICON) -endif - -ifeq ($(strip $(NO_NACP)),) - export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp -endif - -ifneq ($(APP_TITLEID),) - export NACPFLAGS += --titleid=$(APP_TITLEID) -endif - -ifneq ($(ROMFS),) - export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS) -endif - -.PHONY: $(BUILD) clean all - -#--------------------------------------------------------------------------------- -all: $(BUILD) - - -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile - -#--------------------------------------------------------------------------------- -clean: - @rm -fr $(BUILD) $(TARGET).ovl $(TARGET).nro $(TARGET).nacp $(TARGET).elf - - -#--------------------------------------------------------------------------------- -else -.PHONY: all - -DEPENDS := $(OFILES:.o=.d) - -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- -all : $(OUTPUT).ovl - -$(OUTPUT).ovl : $(OUTPUT).elf $(OUTPUT).nacp - @elf2nro $< $@ $(NROFLAGS) - @echo "built ... $(notdir $(OUTPUT).ovl)" - -$(OUTPUT).elf : $(OFILES) - -$(OFILES_SRC) : $(HFILES_BIN) - -#--------------------------------------------------------------------------------- -# you need a rule like this for each extension you use as binary data -#--------------------------------------------------------------------------------- -%.bin.o %_bin.h : %.bin -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - --include $(DEPENDS) - -#--------------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------------- diff --git a/TrainingModpackOverlay/README.md b/TrainingModpackOverlay/README.md deleted file mode 100644 index 366a9a40..00000000 --- a/TrainingModpackOverlay/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# ovlSysmodule - -A Tesla overlay that allows you to toggle sysmodules on the fly - -## Installation - -Download the latest ovlSysmodules.ovl from the release page and drop it into the /switch/.overlays folder on your Switch's SD card diff --git a/TrainingModpackOverlay/include/clickable_list_item.hpp b/TrainingModpackOverlay/include/clickable_list_item.hpp deleted file mode 100644 index 22e5300e..00000000 --- a/TrainingModpackOverlay/include/clickable_list_item.hpp +++ /dev/null @@ -1,81 +0,0 @@ - -#pragma once - -#include - -class ClickableListItem : public tsl::elm::ListItem -{ -public: - ClickableListItem(std::string text, - const std::vector values, - int* defaultPos, - const std::string data, - int index, - std::string title, - std::string help) - : tsl::elm::ListItem(text), m_values(values), m_curValue(defaultPos), extdata(data), title(title), help(help) - { - this->index = index; - this->setValue(""); - } - - ~ClickableListItem() {} - - tsl::elm::Element* requestFocus(Element* oldFocus, tsl::FocusDirection direction) - { - return ListItem::requestFocus(oldFocus, direction); - } - - void layout(u16 parentX, u16 parentY, u16 parentWidth, u16 parentHeight) - { - ListItem::layout(parentX, parentY, parentWidth, parentHeight); - } - - bool onClick(u64 keys) - { - if(keys & KEY_Y) - { - if(this->m_helpListener != nullptr) - { - this->m_helpListener(this->title, this->help); - return true; - } - } - if(keys & KEY_A) - { - if(this->m_clickListener != nullptr) - { - this->m_clickListener(this->m_values, this->m_curValue, this->extdata, this->index, this->title, this->help); - return true; - } - } - - return false; - } - - int getCurValue() { return *(this->m_curValue); } - void setCurValue(int value) { *(this->m_curValue) = value; } - - const std::string getExtData() { return this->extdata; } - - const std::vector getValues() { return this->m_values; } - - void setClickListener( - std::function, int*, std::string, int index, std::string title, std::string help)> - clickListener) - { - this->m_clickListener = clickListener; - } - void setHelpListener(std::function helpListener) { this->m_helpListener = helpListener; } - -private: - const std::vector m_values; - int* m_curValue; - std::function, int*, std::string, int, std::string, std::string)> m_clickListener = - nullptr; - std::function m_helpListener = nullptr; - const std::string extdata; - const std::string title; - const std::string help; - int index; -}; diff --git a/TrainingModpackOverlay/include/cpp_utils.hpp b/TrainingModpackOverlay/include/cpp_utils.hpp deleted file mode 100644 index 29fd26a4..00000000 --- a/TrainingModpackOverlay/include/cpp_utils.hpp +++ /dev/null @@ -1,159 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace detail -{ -template struct BitFlags -{ - using UnderlyingType = U; - using Type = T; - - constexpr static const UnderlyingType s_validMask = (UnderlyingType{1u << *Type::Count} - UnderlyingType{1}); - - struct NoneType - {}; - struct AllType - {}; - - UnderlyingType m_bits; - - constexpr static const AllType All{}; - constexpr static const NoneType None{}; - - BitFlags() = default; - BitFlags(const BitFlags&) = default; - - constexpr BitFlags(NoneType) : m_bits(0) {} - constexpr BitFlags(AllType) : m_bits(s_validMask) {} - constexpr explicit BitFlags(UnderlyingType t) : m_bits(s_validMask & t) {} - - BitFlags& operator=(const BitFlags&) = default; - ~BitFlags() = default; - - constexpr BitFlags(Type t) : m_bits{UnderlyingType{1} << static_cast>(t)} {} - - constexpr BitFlags& operator|=(BitFlags rhs) - { - m_bits |= rhs.m_bits; - return *this; - } - constexpr BitFlags& operator&=(BitFlags rhs) - { - m_bits &= rhs.m_bits; - return *this; - } - constexpr BitFlags& operator-=(BitFlags rhs) - { - m_bits &= ~rhs.m_bits; - return *this; - } - - explicit operator bool() const { return m_bits != 0; } -}; - -template constexpr BitFlags operator|(BitFlags lhs, BitFlags rhs) -{ - lhs |= rhs; - return lhs; -} - -template constexpr BitFlags operator&(BitFlags lhs, BitFlags rhs) -{ - lhs &= rhs; - return lhs; -} - -template constexpr BitFlags operator-(BitFlags lhs, BitFlags rhs) -{ - lhs -= rhs; - return lhs; -} -template constexpr BitFlags operator-(BitFlags lhs, T rhs) -{ - lhs -= rhs; - return lhs; -} - -template constexpr BitFlags operator-(T lhs, BitFlags rhs) -{ - rhs -= lhs; - return rhs; -} - -template constexpr BitFlags operator|(BitFlags lhs, T rhs) -{ - lhs |= rhs; - return lhs; -} - -template constexpr BitFlags operator|(T lhs, BitFlags rhs) -{ - rhs |= lhs; - return rhs; -} - -template constexpr bool operator&(BitFlags lhs, T rhs) -{ - lhs &= rhs; - return lhs.m_bits != 0; -} - -template constexpr bool operator&(T lhs, BitFlags rhs) -{ - rhs &= lhs; - return rhs.m_bits != 0; -} - -template struct FlagType; - -template using FlagTypeT = typename FlagType::Type; - -template struct EnumArray; - -} // namespace detail - -#define DEFINE_FLAGS_UT(TypeName, UnderlyingType) \ - using TypeName##s = detail::BitFlags; \ - constexpr TypeName##s operator|(TypeName lhs, TypeName rhs) { return TypeName##s{lhs} | TypeName##s{rhs}; } \ - namespace detail \ - { \ - template<> struct FlagType \ - { \ - using Type = TypeName##s; \ - }; \ - } - -#define DEFINE_FLAGS(TypeName) DEFINE_FLAGS_UT(TypeName, uint32_t) -#define ENUM_X(type, e, y) e, -#define ENUM_QUAL_X(type, e, y) type::e, -#define ENUM_NAME_PAIR(type, e, y) {type::e, y}, -#define CASE_X(type, e, y) \ - case type::e: \ - return y; -#define DEFINE_ENUM_CLASS_TYPE(Name, Type) \ - enum class Name : Type \ - { \ - ENUM_CLASS_##Name(Name, ENUM_X) Count \ - }; \ - constexpr auto operator*(Name t) { return static_cast>(t); } \ - namespace detail \ - { \ - template<> struct EnumArray \ - { \ - constexpr static const std::array, *Name::Count> values{ \ - {ENUM_CLASS_##Name(Name, ENUM_NAME_PAIR)}}; \ - }; \ - } \ - constexpr const char* toString(Name t) \ - { \ - if(t < Name::Count) \ - { \ - return detail::EnumArray::values[*t].second; \ - } \ - return "UNKNWON"; \ - } \ - DEFINE_FLAGS_UT(Name, Type) -#define DEFINE_ENUM_CLASS(Name) DEFINE_ENUM_CLASS_TYPE(Name, uint32_t) diff --git a/TrainingModpackOverlay/include/gui_help.hpp b/TrainingModpackOverlay/include/gui_help.hpp deleted file mode 100644 index 7d1d888d..00000000 --- a/TrainingModpackOverlay/include/gui_help.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once -#include - -static char help_text_global[1024]; - -class GuiHelp : public tsl::Gui -{ -public: - GuiHelp(std::string title, std::string help) : m_title(std::move(title)), m_help(std::move(help)) {} - - virtual tsl::elm::Element* createUI() override - { - auto rootFrame = new tsl::elm::OverlayFrame(m_title, "Help"); - - snprintf(help_text_global, sizeof help_text_global, "%s", m_help.c_str()); - - auto help_text = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer* renderer, u16 x, u16 y, u16 w, u16 h) { - renderer->drawString(help_text_global, false, 45, 125, 20, renderer->a(0xFFFF)); - }); - - rootFrame->setContent(help_text); - - return rootFrame; - } - - virtual void update() override {} - virtual bool handleInput(u64 keysDown, - u64 keysHeld, - touchPosition touchInput, - JoystickPosition leftJoyStick, - JoystickPosition rightJoyStick) override - { - return false; - } - - std::string m_title; - std::string m_help; -}; \ No newline at end of file diff --git a/TrainingModpackOverlay/include/gui_main.hpp b/TrainingModpackOverlay/include/gui_main.hpp deleted file mode 100644 index cf73940f..00000000 --- a/TrainingModpackOverlay/include/gui_main.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include -#include -#include "value_list_item.hpp" - -class GuiMain : public tsl::Gui -{ -private: - FsFileSystem m_fs; - tsl::elm::ToggleListItem* toggleItem = nullptr; - std::vector valueListItems; - -public: - GuiMain(); - ~GuiMain(); - - virtual tsl::elm::Element* createUI(); - virtual void update() override; - void applyChanges(); -}; \ No newline at end of file diff --git a/TrainingModpackOverlay/include/gui_sublist.hpp b/TrainingModpackOverlay/include/gui_sublist.hpp deleted file mode 100644 index 406c4a04..00000000 --- a/TrainingModpackOverlay/include/gui_sublist.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include -#include -#include "clickable_list_item.hpp" - -class GuiSublist : public tsl::Gui -{ -private: - std::vector listItems; - std::vector menuItems; - int* index; - std::string extData; - std::string title; - std::string help; - -public: - GuiSublist(std::vector menuItems, int* index, std::string extData, std::string title, std::string help); - ~GuiSublist(); - - virtual tsl::elm::Element* createUI(); - virtual void update() override; - void applyChanges(); - virtual void setClickListener(ClickableListItem* item); -}; - -class GuiLambda : public tsl::Gui -{ - std::function m_createUI; - tsl::Gui* m_guiMain; - -public: - virtual tsl::elm::Element* createUI() override - { - if(m_createUI) return m_createUI(); - return nullptr; - } - virtual void update() override - { - m_guiMain->update(); - } - GuiLambda(std::function createUIFunc, tsl::Gui* guiMain) : m_createUI(std::move(createUIFunc)), m_guiMain(guiMain) {} -}; \ No newline at end of file diff --git a/TrainingModpackOverlay/include/ini_settings.hpp b/TrainingModpackOverlay/include/ini_settings.hpp deleted file mode 100644 index 54c827a0..00000000 --- a/TrainingModpackOverlay/include/ini_settings.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#include - -static const char* SYSTEM_SETTINGS_FILE = "/atmosphere/config/system_settings.ini"; - -static tsl::hlp::ini::IniData readSettings() -{ - /* Open Sd card filesystem. */ - FsFileSystem fsSdmc; - if(R_FAILED(fsOpenSdCardFileSystem(&fsSdmc))) return {}; - tsl::hlp::ScopeGuard fsGuard([&] { fsFsClose(&fsSdmc); }); - - /* Open config file. */ - FsFile fileConfig; - if(R_FAILED(fsFsOpenFile(&fsSdmc, SYSTEM_SETTINGS_FILE, FsOpenMode_Read, &fileConfig))) return {}; - tsl::hlp::ScopeGuard fileGuard([&] { fsFileClose(&fileConfig); }); - - /* Get config file size. */ - s64 configFileSize; - if(R_FAILED(fsFileGetSize(&fileConfig, &configFileSize))) return {}; - - /* Read and parse config file. */ - std::string configFileData(configFileSize, '\0'); - u64 readSize; - Result rc = fsFileRead(&fileConfig, 0, configFileData.data(), configFileSize, FsReadOption_None, &readSize); - if(R_FAILED(rc) || readSize != static_cast(configFileSize)) return {}; - - return tsl::hlp::ini::parseIni(configFileData); -} - -static void writeSettings(tsl::hlp::ini::IniData const& iniData) -{ - /* Open Sd card filesystem. */ - FsFileSystem fsSdmc; - if(R_FAILED(fsOpenSdCardFileSystem(&fsSdmc))) return; - tsl::hlp::ScopeGuard fsGuard([&] { fsFsClose(&fsSdmc); }); - - std::string iniString = tsl::hlp::ini::unparseIni(iniData); - - fsFsDeleteFile(&fsSdmc, SYSTEM_SETTINGS_FILE); - fsFsCreateFile(&fsSdmc, SYSTEM_SETTINGS_FILE, iniString.length(), 0); - - /* Open config file. */ - FsFile fileConfig; - if(R_FAILED(fsFsOpenFile(&fsSdmc, SYSTEM_SETTINGS_FILE, FsOpenMode_Write, &fileConfig))) return; - tsl::hlp::ScopeGuard fileGuard([&] { fsFileClose(&fileConfig); }); - - fsFileWrite(&fileConfig, 0, iniString.c_str(), iniString.length(), FsWriteOption_Flush); -} - -static void updateSettings(tsl::hlp::ini::IniData const& changes) -{ - tsl::hlp::ini::IniData iniData = readSettings(); - for(auto& section : changes) - { - for(auto& keyValue : section.second) - { - iniData[section.first][keyValue.first] = keyValue.second; - } - } - writeSettings(iniData); -} \ No newline at end of file diff --git a/TrainingModpackOverlay/include/overflow_list.hpp b/TrainingModpackOverlay/include/overflow_list.hpp deleted file mode 100644 index c01a8d5d..00000000 --- a/TrainingModpackOverlay/include/overflow_list.hpp +++ /dev/null @@ -1,124 +0,0 @@ -#include - -class OverflowList : public tsl::elm::List { - public: - OverflowList() : tsl::elm::List() {} - - virtual tsl::elm::Element* requestFocus(tsl::elm::Element *oldFocus, tsl::FocusDirection direction) override { - tsl::elm::Element *newFocus = nullptr; - - if (this->m_clearList || this->m_itemsToAdd.size() > 0) - return nullptr; - - if (direction == tsl::FocusDirection::None) { - u16 i = 0; - - if (oldFocus == nullptr) { - s32 elementHeight = 0; - while (elementHeight < this->m_offset && i < this->m_items.size() - 1) { - i++; - elementHeight += this->m_items[i]->getHeight(); - } - } - - for (; i < this->m_items.size(); i++) { - newFocus = this->m_items[i]->requestFocus(oldFocus, direction); - - if (newFocus != nullptr) { - this->m_focusedIndex = i; - - this->updateScrollOffset(); - return newFocus; - } - } - } else { - if (direction == tsl::FocusDirection::Down) { - - for (u16 i = this->m_focusedIndex + 1; i < this->m_items.size(); i++) { - newFocus = this->m_items[i]->requestFocus(oldFocus, direction); - - if (newFocus != nullptr && newFocus != oldFocus) { - this->m_focusedIndex = i; - - this->updateScrollOffset(); - return newFocus; - } - } - - if (this->m_focusedIndex == this->m_items.size() - 1) { - for (u16 i = 0; i < this->m_items.size(); i++) { - newFocus = this->m_items[i]->requestFocus(oldFocus, direction); - - if (newFocus != nullptr && newFocus != oldFocus) { - this->m_focusedIndex = i; - - this->updateScrollOffset(); - return newFocus; - } - } - } - - return oldFocus; - } else if (direction == tsl::FocusDirection::Up) { - if (this->m_focusedIndex > 0) { - - for (u16 i = this->m_focusedIndex - 1; i >= 0; i--) { - if (i > this->m_items.size() || this->m_items[i] == nullptr) - return oldFocus; - else - newFocus = this->m_items[i]->requestFocus(oldFocus, direction); - - if (newFocus != nullptr && newFocus != oldFocus) { - this->m_focusedIndex = i; - - this->updateScrollOffset(); - return newFocus; - } - } - - } - - for (u16 i = this->m_items.size() - 1; i >= 0; i--) { - if (i <= this->m_items.size() && this->m_items[i] != nullptr) - newFocus = this->m_items[i]->requestFocus(oldFocus, direction); - - if (newFocus != nullptr && newFocus != oldFocus) { - this->m_focusedIndex = i; - - this->updateScrollOffset(); - return newFocus; - } - } - - return oldFocus; - } - } - - return oldFocus; - } - - private: - virtual void updateScrollOffset() { - if (this->getInputMode() != tsl::InputMode::Controller) - return; - - if (this->m_listHeight <= this->getHeight()) { - this->m_nextOffset = 0; - this->m_offset = 0; - - return; - } - - this->m_nextOffset = 0; - for (u16 i = 0; i < this->m_focusedIndex; i++) - this->m_nextOffset += this->m_items[i]->getHeight(); - - this->m_nextOffset -= this->getHeight() / 3; - - if (this->m_nextOffset < 0) - this->m_nextOffset = 0; - - if (this->m_nextOffset > (this->m_listHeight - this->getHeight()) + 50) - this->m_nextOffset = (this->m_listHeight - this->getHeight() + 50); - } -}; \ No newline at end of file diff --git a/TrainingModpackOverlay/include/overlay_frame_with_help.hpp b/TrainingModpackOverlay/include/overlay_frame_with_help.hpp deleted file mode 100644 index 78fb4179..00000000 --- a/TrainingModpackOverlay/include/overlay_frame_with_help.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#include - -class OverlayFrameWithHelp : public tsl::elm::OverlayFrame -{ -public: - OverlayFrameWithHelp(const std::string& title, const std::string& subtitle) : tsl::elm::OverlayFrame(title, subtitle) - {} - - virtual void draw(tsl::gfx::Renderer* renderer) override - { - renderer->fillScreen(a(tsl::style::color::ColorFrameBackground)); - renderer->drawRect(tsl::cfg::FramebufferWidth - 1, 0, 1, tsl::cfg::FramebufferHeight, a(0xF222)); - - renderer->drawString(this->m_title.c_str(), false, 20, 50, 30, a(tsl::style::color::ColorText)); - renderer->drawString(this->m_subtitle.c_str(), false, 20, 70, 15, a(tsl::style::color::ColorDescription)); - - renderer->drawRect(15, tsl::cfg::FramebufferHeight - 73, tsl::cfg::FramebufferWidth - 30, 1, a(tsl::style::color::ColorText)); - - renderer->drawString("\uE0E1 Back \uE0E0 OK \uE0E3 Help", false, 30, 693, 23, a(tsl::style::color::ColorText)); - - if (this->m_contentElement != nullptr) - this->m_contentElement->frame(renderer); - } -}; \ No newline at end of file diff --git a/TrainingModpackOverlay/include/taunt_toggles.hpp b/TrainingModpackOverlay/include/taunt_toggles.hpp deleted file mode 100644 index dd653c52..00000000 --- a/TrainingModpackOverlay/include/taunt_toggles.hpp +++ /dev/null @@ -1,368 +0,0 @@ -#pragma once - -#define NONE 0 - -#include - -#include "cpp_utils.hpp" - -const std::vector on_off{"Off", "On"}; -// clang-format off -#define ENUM_CLASS_OnOffFlag(type,x) \ - x(type,On,"On") - -// clang-format on -DEFINE_ENUM_CLASS(OnOffFlag); - -// Frame Advantage -const std::vector frame_advantage_items{""}; -const std::string frame_advantage_help = R""""( -Show frame advantage when -hitting a CPU's shield. - -This is comparing true frames -of actionability between the -CPU and player. - -Use this to practice optimal -aerial heights and specific -safe hitboxes.)""""; - -// Input delay -const std::vector input_delay_items{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"}; -const std::string input_delay_help = R""""( -In frames. - -Emulate input delay -to practice in a online -environment.)""""; - -// Side Taunt - -// DI / Left Stick -/* - 0, 0.785398, 1.570796, 2.356194, -3.14159, -2.356194, -1.570796, -0.785398 - 0, pi/4, pi/2, 3pi/4, pi, 5pi/4, 3pi/2, 7pi/4 -*/ - -/* DI */ -// clang-format off -#define ENUM_CLASS_Direction(type,x) \ - x(type,Out,"Out") \ - x(type,UpOut,"Up Out") \ - x(type,Up,"Up") \ - x(type,UpIn,"Up In") \ - x(type,In,"In") \ - x(type,DownIn,"Down In") \ - x(type,Down,"Down") \ - x(type,DownOut,"Down Out")\ - x(type,Nothing,"Neutral") - -DEFINE_ENUM_CLASS(Direction); -const std::string di_help = R""""( -Specified Direction -CPUs DI in the direction specified -(relative to the player's facing -position). -)""""; - -const std::string sdi_help = R""""( -Specified Direction -CPUs SDI in the direction specified -(relative to the player's facing -position) every four frames -during hitlag. -)""""; - -// Left Stick -const std::string air_dodge_direction_help = R""""( -Air Dodge Direction -(relative to the player's facing -position). -)""""; - -// Ledge Option -// clang-format off -#define ENUM_CLASS_LedgeFlag(type,x) \ - x(type,Neutral,"Neutral") \ - x(type,Roll,"Roll") \ - x(type,Jump,"Jump") \ - x(type,Attack,"Attack") \ - x(type,Wait,"Wait") - - -// clang-format on - -DEFINE_ENUM_CLASS(LedgeFlag); -const std::string ledge_help = R""""( -CPUs will perform a ledge option -among the selected options. - -CPUs will also perform a defensive -option after getting up. -)""""; - -const std::string ledge_delay_help = R""""( -Frames to delay ledge option.)""""; - -// Tech Option - -// clang-format off -#define ENUM_CLASS_TechFlag(type,x) \ - x(type,Miss,"Miss Tech") \ - x(type,RollF,"RollF") \ - x(type,RollB,"RollB") \ - x(type,InPlace,"In Place") - -// clang-format on -DEFINE_ENUM_CLASS(TechFlag); - -constexpr const char* const tech_help = R""""( -CPUs will perform a random -tech option among the selected -options. - -CPUs will also perform a defensive -option after getting up. - -For wall tech jumps set it to RollF -)""""; - -// Missed Tech Option - -// clang-format off -#define ENUM_CLASS_MissTechFlag(type,x) \ - x(type,Getup,"Normal Getup") \ - x(type,Attack,"Getup Attack") \ - x(type,RollF,"RollF") \ - x(type,RollB,"RollB") - -// clang-format on -DEFINE_ENUM_CLASS(MissTechFlag); - -constexpr const char* const miss_tech_help = R""""( -CPUs will perform a random -option after missing a tech -among the selected options. - -CPUs will also perform a defensive -option after getting up.)""""; - -// Defensive States - -// clang-format off -#define ENUM_CLASS_DefensiveFlag(type,x) \ - x(type,SpotDodge,"Spotdodge") \ - x(type,RollF,"RollF") \ - x(type,RollB,"RollB") \ - x(type,Jab,"Jab")\ - x(type,Shield,"Shield") - -// clang-format on -DEFINE_ENUM_CLASS(DefensiveFlag); - -const std::string defensive_help = R""""( -Choose the defensive option a CPU -will perform after teching or -getting up from the ledge. - -The option will be random -among the selected options. -)""""; - -// Mash States -const std::string mash_help = R""""( -Use this toggle along with the Shield -Options toggle to practice moves on -shield. - -The option will be random -among the selected options. - -CPUs will mash on the first frame out -of hitstun or out of specific states. -)""""; - -// Action items (Follow Up only atm) - -// clang-format off -#define ENUM_CLASS_ActionFlag(type,x) \ - x(type,Airdodge,"Airdodge") x(type,Jump,"Jump") x(type,Shield,"Shield") x(type,Spotdodge,"Spotdodge") x(type,RollF,"Roll F") x(type,RollB,"Roll B") \ - x(type,Nair,"Neutral Air") x(type,Fair,"Forward Air") x(type,Bair,"Back Air") x(type,Uair,"Up Air") x(type,Dair,"Down Air") \ - x(type,NeutralB,"Neutral B") x(type,SideB,"Side B") x(type,UpB,"Up B") x(type,DownB,"Down B") \ - x(type,FSmash,"Forward Smash") x(type,USmash,"Up Smash") x(type,DSmash,"Down Smash") \ - x(type,Jab,"Jab") x(type,FTilt,"Ftilt") x(type,UTilt,"Utilt") x(type,Dtilt,"Dtilt") \ - x(type,Grab,"Grab") x(type,Dash,"Dash") x(type,DashAttack,"Dash Attack") - -// clang-format on -DEFINE_ENUM_CLASS(ActionFlag); - -const std::string follow_up_help = R""""( -The selected action will be -buffered after the specified -mash option. - -The option will be random -among the selected options. -)""""; - -// Hitbox visualization -const std::string hitbox_help = R""""( -Currently, hitboxes and -grabboxes are supported. - -Original move effects are -paused during normal attacks -and specials when hitbox -visualization is active.)""""; - -// Stage Hazards -const std::string hazards_help = R""""( -Toggle state hazards on/off for -Training Mode. - -Only works outside of a match. -Make sure to turn them on/off -before leaving the Character -Select Screen. - -If you change this while in training, -make sure to restart training mode. -)""""; - -// Save states -const std::vector empty_items{""}; -const std::string save_states_help = R""""( -Press Grab + Down Taunt at any -time to save the state of the -training mode for you and the -CPU. - -Press Grab + Up Taunt at any -time to revert to a -previously saved state. - -The following attributes -are saved: -- Percent -- Position -- Facing direction)""""; - -const std::string reset_menu_help = R""""( -Reset menu to default -configuration. Please also -use on the first boot after -upgrading Training Modpack -versions.)""""; - -// Shield States -#define SHIELD_INFINITE 1 -#define SHIELD_HOLD 2 -const std::vector shield_items{"None", "Infinite", "Hold", "Constant"}; -const std::string shield_help = R""""( -Use these toggles in conjunction -with Mash toggles to practice -moves on shield. - -Infinite -CPUs will hold a shield that does -not deteriorate over time or -by damage. - -Hold -CPUs will hold a normal shield. -This shield will not deteriorate -until hit once.) - -Constant -Shield will take damage but not deteriorate - -)""""; - -// OOS -const std::string oos_help = R""""( -Option to delay oos options -until a certain number of hits -have connected. - -Consecutive hits that keep the -CPU locked in shield stun -between hits will count -as a single hit.)""""; - -const std::string reaction_time_help = R""""( -Additional reaction time -in frames. - -Used to delay OOS Options.)""""; - -const std::string shield_tilt_help = R""""( -Shield Tilt Direction -)""""; - -// Mash in neutral -const std::string mash_neutral_help = R""""( -Force mash options to -always occur, not just -out of specific states.)""""; - -// clang-format off -#define ENUM_CLASS_DelayFlag(type,x) \ - x(type,D0,"0") \ - x(type,D1,"1") x(type,D2,"2") x(type,D3,"3") x(type,D4,"4") x(type,D5,"5") \ - x(type,D6,"6") x(type,D7,"7") x(type,D8,"8") x(type,D9,"9") x(type,D10,"10") \ - x(type,D11,"11") x(type,D12,"12") x(type,D13,"13") x(type,D14,"14") x(type,D15,"15") \ - x(type,D16,"16") x(type,D17,"17") x(type,D18,"18") x(type,D19,"19") x(type,D20,"20") \ - x(type,D21,"21") x(type,D22,"22") x(type,D23,"23") x(type,D24,"24") x(type,D25,"25") \ - x(type,D26,"26") x(type,D27,"27") x(type,D28,"28") x(type,D29,"29") x(type,D30,"30") \ -// clang-format on - -DEFINE_ENUM_CLASS(DelayFlag); - -#define ENUM_CLASS_BoolFlag(type,x) \ - x(type,True,"True") x(type,False,"False") - -DEFINE_ENUM_CLASS(BoolFlag); - -const std::string fast_fall_help = R""""( -CPUs will fast fall -out of jumps and aerial -attacks as soon as possible.)""""; - -const std::string fast_fall_delay_help = R""""( -Frames to delay CPU -fast fall.)""""; - -const std::string falling_aerials_help = R""""( -CPUs will only begin -aerials at the apex of -their jump.)""""; - -const std::string aerial_delay_help = R""""( -Frames to delay CPU Aerial.)""""; - -const std::string full_hop_help = R""""( -CPUs will full hop -rather than short hop -aerials.)""""; - -#define ENUM_CLASS_AttackAngleFlag(type,x) \ - x(type,Neutral,"Neutral") x(type,Up,"Up") x(type,Down,"Down") -DEFINE_ENUM_CLASS(AttackAngleFlag); - -const std::string attack_angle_help = R""""( -Set angleable tilt and smash attacks.)""""; - -const std::string save_damage_help = R""""( -Set if save states should apply to damage.)""""; - -#define NORMAL 0 -const std::vector strength_items{ "Normal", "Medium", "High"}; -const std::string sdi_strength_help = R""""( -How many frames between each SDI input - -Normal 8 -Medium 6 -High 4 - -)""""; diff --git a/TrainingModpackOverlay/include/value_list_item.hpp b/TrainingModpackOverlay/include/value_list_item.hpp deleted file mode 100644 index fc68ee21..00000000 --- a/TrainingModpackOverlay/include/value_list_item.hpp +++ /dev/null @@ -1,185 +0,0 @@ -#pragma once - -#include -#include -#include -#include "gui_help.hpp" -#include "gui_sublist.hpp" -#include "cpp_utils.hpp" - -class ValueListItem : public tsl::elm::ListItem -{ -public: - ValueListItem(std::string text, - const std::vector values, - int* defaultPos, - const std::string data, - const std::string help) - : tsl::elm::ListItem(text), m_values(values), m_curValue(defaultPos), extdata(data), help(help) - { - this->setValue(m_values[*m_curValue]); - - this->initEventListener(); - } - - ~ValueListItem() {} - - void applyChanges() - { - int value = this->getCurValue(); - this->setValue(this->getValues()[value]); - this->setCurValue(value); - } - - tsl::elm::Element* requestFocus(Element* oldFocus, tsl::FocusDirection direction) - { - return ListItem::requestFocus(oldFocus, direction); - } - - void layout(u16 parentX, u16 parentY, u16 parentWidth, u16 parentHeight) - { - ListItem::layout(parentX, parentY, parentWidth, parentHeight); - } - - bool onClick(u64 keys) - { - if(keys & KEY_A) - { - if(this->m_valueChangeListener != nullptr) - { - this->m_valueChangeListener(this->m_values, this->m_curValue, this->extdata, this->getText(), this->help); - return true; - } - - return true; - } - - return false; - } - - int getCurValue() { return *(this->m_curValue); } - void setCurValue(int value) { *(this->m_curValue) = value; } - - const std::string getExtData() { return this->extdata; } - - const std::vector getValues() { return this->m_values; } - - void setStateChangedListener( - std::function, int*, std::string, std::string, std::string)> valueChangeListener) - { - this->m_valueChangeListener = valueChangeListener; - } - -protected: - void initEventListener() - { - this->setStateChangedListener( - [](std::vector menuItems, int* val, std::string data, std::string title, std::string helpTxt) { - tsl::changeTo(menuItems, val, data, title, helpTxt); - }); - } - -private: - const std::vector m_values; - int* m_curValue; - std::function, int*, std::string, std::string, std::string)> m_valueChangeListener = - nullptr; - const std::string extdata; - const std::string help; -}; - -template class BitFlagToggleListItem : public tsl::elm::ToggleListItem -{ -public: - using FlagType = detail::FlagTypeT; - -private: - T m_mask; - FlagType* m_value; - std::string m_name; - std::string m_help; - -public: - BitFlagToggleListItem(const std::string& text, T mask, FlagType* value, std::string name = "", std::string help = "") - : tsl::elm::ToggleListItem(text, (mask & *value) != 0, "\uE14B", "\uE14C"), m_mask(mask), m_value(value), m_name(name), m_help(help) - { - setStateChangedListener([this](bool v) { - if(v) - { - *m_value = *m_value | m_mask; - } - else - { - *m_value = *m_value - m_mask; - } - }); - } - virtual bool onClick(u64 keys) override - { - // temp band-aid for issues with ToggleListItem - if(keys & KEY_A) - { - setState(!m_state); - return ListItem::onClick(keys); - } - else if(keys & KEY_Y) - { - if (m_help != "") { - tsl::changeTo(m_name, m_help); - } - } - return false; - } - virtual void setState(bool state) override - { - // temp band-aid for issues with ToggleListItem - bool stateChanged = state != this->m_state; - ToggleListItem::setState(state); - if(stateChanged && m_stateChangedListener) - { - m_stateChangedListener(state); - } - } - virtual ~BitFlagToggleListItem() = default; -}; - -class SetToggleListItem : public tsl::elm::ListItem -{ - std::vector m_itemsOn; - std::vector m_itemsOff; - std::string m_name; - std::string m_help; - -public: - SetToggleListItem(std::vector itemsOn, - std::vector itemsOff, - const std::string& text, - const std::string name = "", - const std::string help = "", - const std::string& value = "") - : tsl::elm::ListItem(text, value), m_itemsOn(std::move(itemsOn)), m_itemsOff(std::move(itemsOff)), m_name(name), m_help(help) - { - setClickListener([this](u64 keys) -> bool { - if(keys & KEY_A) - { - for(auto it : m_itemsOn) - { - it->setState(true); - } - for(auto it : m_itemsOff) - { - it->setState(false); - } - return true; - } - else if(keys & KEY_Y) - { - if (m_help != "") { - tsl::changeTo(m_name, m_help); - } - } - return false; - }); - } - virtual ~SetToggleListItem() = default; -}; \ No newline at end of file diff --git a/TrainingModpackOverlay/libs/libtesla b/TrainingModpackOverlay/libs/libtesla deleted file mode 160000 index a68af19e..00000000 --- a/TrainingModpackOverlay/libs/libtesla +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a68af19eda8e2b1d51008a2e1a1b71649460f901 diff --git a/TrainingModpackOverlay/source/gui_main.cpp b/TrainingModpackOverlay/source/gui_main.cpp deleted file mode 100644 index 34dff057..00000000 --- a/TrainingModpackOverlay/source/gui_main.cpp +++ /dev/null @@ -1,539 +0,0 @@ -#include -#include "gui_main.hpp" -#include "gui_help.hpp" -#include "overflow_list.hpp" -#include "overlay_frame_with_help.hpp" -#include "value_list_item.hpp" -#include "clickable_list_item.hpp" -#include "ini_settings.hpp" -#include "taunt_toggles.hpp" - -static struct TrainingModpackMenu -{ - OnOffFlags HITBOX_VIS = OnOffFlag::On; - OnOffFlags STAGE_HAZARDS = OnOffFlags::None; - Directions DI_STATE = Directions::None; - Directions SDI_STATE = Directions::None; - int SDI_STRENGTH = NORMAL; - Directions AIR_DODGE_DIR = Directions::None; - ActionFlags MASH_STATE = ActionFlags::None; - ActionFlags FOLLOW_UP = ActionFlags::None; - AttackAngleFlags ATTACK_ANGLE = AttackAngleFlags::None; - LedgeFlags LEDGE_STATE = LedgeFlags::All; - DelayFlags LEDGE_DELAY = DelayFlags::All; - TechFlags TECH_STATE = TechFlags::All; - MissTechFlags MISS_TECH_STATE = MissTechFlags::All; - int SHIELD_STATE = NONE; - DefensiveFlags DEFENSIVE_STATE = DefensiveFlags::All; - DelayFlags OOS_OFFSET = DelayFlags::None; - DelayFlags REACTION_TIME = DelayFlags::None; - Directions SHIELD_TILT = Directions::None; - OnOffFlags MASH_IN_NEUTRAL = OnOffFlags::None; - BoolFlags FAST_FALL = BoolFlags::None; - DelayFlags FAST_FALL_DELAY = DelayFlags::None; - BoolFlags FALLING_AERIALS = BoolFlags::None; - DelayFlags AERIAL_DELAY = DelayFlags::None; - BoolFlags FULL_HOP = BoolFlags::None; - int INPUT_DELAY = 0; - OnOffFlags SAVE_DAMAGE = OnOffFlag::On; -} menu; - -static struct TrainingModpackMenu defaultMenu = menu; - -static int FRAME_ADVANTAGE = 0; - -u64 pidSmash = 0; -static const char* TRAINING_MOD_LOG = "/TrainingModpack/training_modpack.log"; -static const char* TRAINING_MOD_FRAME_ADV_LOG = "/TrainingModpack/training_modpack_frame_adv.log"; -static const char* TRAINING_MOD_CONF = "/TrainingModpack/training_modpack_menu.conf"; - -GuiMain::GuiMain() -{ - smInitialize(); - pminfoInitialize(); - pmbmInitialize(); - smExit(); - - pmdmntGetProcessId(&pidSmash, 0x01006A800016E000); - - Result rc = fsOpenSdCardFileSystem(&this->m_fs); - if(R_FAILED(rc)) return; - - FsFile menuFile; - rc = fsFsOpenFile(&this->m_fs, TRAINING_MOD_CONF, FsOpenMode_Read, &menuFile); - if(R_FAILED(rc)) return; - - u64 bytesRead; - rc = fsFileRead(&menuFile, 0, static_cast(&menu), sizeof(menu), FsReadOption_None, &bytesRead); - if(R_FAILED(rc)) - { - fsFileWrite(&menuFile, 0, static_cast(&menu), sizeof(menu), FsOpenMode_Write); - } - - fsFileClose(&menuFile); -} - -GuiMain::~GuiMain() -{ - // apply changes on exit - applyChanges(); - - smInitialize(); - pminfoExit(); - pmbmExit(); - smExit(); -} - -static char FrameAdvantage[672]; - -class FrameAdvantageOverlayFrame : public tsl::elm::OverlayFrame -{ -public: - FrameAdvantageOverlayFrame(const std::string& title, const std::string& subtitle) : tsl::elm::OverlayFrame(title, subtitle) - {} - - virtual void draw(tsl::gfx::Renderer* renderer) override - { - renderer->clearScreen(); - - renderer->drawRect(0, 0, tsl::cfg::FramebufferWidth, 85, a(tsl::style::color::ColorFrameBackground)); - - renderer->drawString(this->m_title.c_str(), false, 20, 50, 30, a(tsl::style::color::ColorText)); - renderer->drawString(this->m_subtitle.c_str(), false, 20, 70, 15, a(tsl::style::color::ColorDescription)); - - if(this->m_contentElement != nullptr) this->m_contentElement->frame(renderer); - } -}; - -class GuiFrameAdvantage : public tsl::Gui -{ -public: - GuiFrameAdvantage() - { - tsl::hlp::requestForeground(false); - smInitialize(); - pminfoInitialize(); - pmbmInitialize(); - smExit(); - - pmdmntGetProcessId(&pidSmash, 0x01006A800016E000); - - Result rc = fsOpenSdCardFileSystem(&this->m_fs); - if(R_FAILED(rc)) return; - } - - ~GuiFrameAdvantage() - { - smInitialize(); - pminfoExit(); - pmbmExit(); - smExit(); - } - - virtual tsl::elm::Element* createUI() override - { - snprintf(FrameAdvantage, 256, "Frame Advantage: %d", FRAME_ADVANTAGE); - auto rootFrame = new FrameAdvantageOverlayFrame(FrameAdvantage, "\uE0A2 + \uE07B Back"); - - this->rootFrame = rootFrame; - - return rootFrame; - } - - virtual void update() override - { - static u32 counter = 0; - - if(counter++ % 10 != 0) return; - - Result rc; - Handle debug; - - if(pidSmash != 0) - { - rc = svcDebugActiveProcess(&debug, pidSmash); - if(R_SUCCEEDED(rc)) - { - u64 frame_adv_addr = 0; - FsFile menuAddrFile; - rc = fsFsOpenFile(&this->m_fs, TRAINING_MOD_FRAME_ADV_LOG, FsOpenMode_Read, &menuAddrFile); - if(R_FAILED(rc)) - { - snprintf(FrameAdvantage, sizeof FrameAdvantage, "Failed to open file with error %d", rc); - rootFrame->setTitle(FrameAdvantage); - svcCloseHandle(debug); - return; - } - - char buffer[100]; - u64 bytesRead; - rc = fsFileRead(&menuAddrFile, 0, buffer, 100, FsReadOption_None, &bytesRead); - if(R_FAILED(rc)) - { - snprintf(FrameAdvantage, sizeof FrameAdvantage, "Failed to read file with error %d", rc); - rootFrame->setTitle(FrameAdvantage); - svcCloseHandle(debug); - return; - } - - fsFileClose(&menuAddrFile); - buffer[bytesRead] = '\0'; - frame_adv_addr = strtoul(buffer, NULL, 16); - - if(frame_adv_addr != 0) - { - rc = svcReadDebugProcessMemory(&FRAME_ADVANTAGE, debug, frame_adv_addr, sizeof(int)); - snprintf(FrameAdvantage, sizeof FrameAdvantage, "Frame Advantage: %d", FRAME_ADVANTAGE); - rootFrame->setTitle(FrameAdvantage); - } - - svcCloseHandle(debug); - } - } - else - { - snprintf(FrameAdvantage, sizeof FrameAdvantage, "Smash is not running."); - rootFrame->setTitle(FrameAdvantage); - } - } - virtual bool handleInput(u64 keysDown, - u64 keysHeld, - touchPosition touchInput, - JoystickPosition leftJoyStick, - JoystickPosition rightJoyStick) override - { - if(keysHeld & KEY_DLEFT) - { - if(keysHeld & KEY_X) - { - tsl::goBack(); - tsl::hlp::requestForeground(true); - return true; - } - } - - // intercept B inputs - if(keysDown & KEY_B) - { - return true; - } - return false; - } - - FrameAdvantageOverlayFrame* rootFrame; - FsFileSystem m_fs; -}; - -namespace -{ -template -tsl::elm::ListItem* createBitFlagOption(T* option, const std::string& name, const std::string& help, GuiMain* guiMain) -{ - using FlagType = typename T::Type; - - auto item = new tsl::elm::ListItem(name); - item->setClickListener([name, help, option, guiMain](u64 keys) -> bool { - if(keys & KEY_A) - { - tsl::changeTo( - [option, name, help]() -> tsl::elm::Element* { - auto toggleList = new OverflowList(); - std::vector items; - for(auto& [flag, str] : detail::EnumArray::values) - { - items.emplace_back(new BitFlagToggleListItem(str, flag, option, name, help)); - } - - auto allOff = new SetToggleListItem({}, items, "None", name, help); - auto allOn = new SetToggleListItem(items, {}, "All", name, help); - - toggleList->addItem(allOn); - toggleList->addItem(allOff); - - for(auto it : items) - { - toggleList->addItem(it); - } - - auto frame = new OverlayFrameWithHelp(name, "Press \uE0E3 for help with these options."); - frame->setContent(toggleList); - return frame; - }, - guiMain); - return true; - } - if(keys & KEY_Y) - { - tsl::changeTo(name, help); - } - return false; - }); - return item; -} -} // namespace - -tsl::elm::Element* GuiMain::createUI() -{ - char buffer[256]; - snprintf(buffer, 256, "Version %s", VERSION); - OverlayFrameWithHelp* rootFrame = new OverlayFrameWithHelp("Training Modpack", buffer); - - auto list = new OverflowList(); - - Result rc; - Handle debug; - - tsl::hlp::ini::IniData iniData = readSettings(); - bool ease_nro_restriction = false; - for(auto& section : iniData) - { - for(auto& keyValue : section.second) - { - if(section.first == "ro") - { - if(keyValue.first == "ease_nro_restriction") - { - ease_nro_restriction = (readSettings()["ro"]["ease_nro_restriction"] == "u8!0x1"); - } - } - } - } - - if(!ease_nro_restriction) - { - tsl::elm::Element* iniShow = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer* renderer, u16 x, u16 y, u16 w, u16 h) { - renderer->drawString( - "Your config file did not have the \nproper configuration to run the \nTraining Modpack.\n\n\nIt has been automatically \nupdated.\n- atmosphere\n---- config\n-------- system_settings.ini\n\n(enable ease_nro_restriction)\n\n\nPlease reboot your Switch.", - false, - 50, - 225, - 20, - tsl::Color(255, 255, 255, 255)); - }); - - updateSettings({{"ro", {{"ease_nro_restriction", "u8!0x1"}}}}); - - rootFrame->setContent(iniShow); - return rootFrame; - } - - if(pidSmash != 0) - { - rc = svcDebugActiveProcess(&debug, pidSmash); - if(R_SUCCEEDED(rc)) - { - svcCloseHandle(debug); - - // Remove because it breaks scrolling up to the bottom of the - // menu, because CategoryHeaders can't requestFocus? - // list->addItem(new tsl::elm::CategoryHeader("Mash", true)); - - list->addItem(createBitFlagOption(&menu.MASH_STATE, "Mash Toggles", mash_help, this)); - list->addItem(createBitFlagOption(&menu.FOLLOW_UP, "Followup Toggles", follow_up_help, this)); - list->addItem(new BitFlagToggleListItem( - "Mash In Neutral", OnOffFlag::On, &menu.MASH_IN_NEUTRAL, "Mash In Neutral", mash_neutral_help)); - list->addItem(createBitFlagOption(&menu.ATTACK_ANGLE, "Attack Angle", attack_angle_help, this)); - - list->addItem(new tsl::elm::CategoryHeader("Left Stick", true)); - - list->addItem(createBitFlagOption(&menu.DI_STATE, "Set DI", di_help, this)); - list->addItem(createBitFlagOption(&menu.SDI_STATE, "Set SDI", sdi_help, this)); - - ValueListItem* sdiItem = - new ValueListItem("SDI Strength", strength_items, &menu.SDI_STRENGTH, "SDI Strength", sdi_strength_help); - list->addItem(sdiItem); - valueListItems.push_back(sdiItem); - - list->addItem(createBitFlagOption(&menu.AIR_DODGE_DIR, "Airdodge Direction", air_dodge_direction_help, this)); - - list->addItem(new tsl::elm::CategoryHeader("Shield", true)); - - ValueListItem* shieldItem = - new ValueListItem("Shield Options", shield_items, &menu.SHIELD_STATE, "shield", shield_help); - list->addItem(shieldItem); - valueListItems.push_back(shieldItem); - - ClickableListItem* frameAdvantageItem = new ClickableListItem("Frame Advantage", - frame_advantage_items, - nullptr, - "frameAdvantage", - 0, - "Frame Advantage", - frame_advantage_help); - frameAdvantageItem->setClickListener([](std::vector values, - int* curValue, - std::string extdata, - int index, - std::string title, - std::string help) { tsl::changeTo(); }); - frameAdvantageItem->setHelpListener( - [](std::string title, std::string help) { tsl::changeTo(title, help); }); - list->addItem(frameAdvantageItem); - - list->addItem(createBitFlagOption(&menu.OOS_OFFSET, "OOS Offset", oos_help, this)); - list->addItem(createBitFlagOption(&menu.REACTION_TIME, "Reaction Time", reaction_time_help, this)); - list->addItem(createBitFlagOption(&menu.SHIELD_TILT, "Shield Tilt", shield_tilt_help, this)); - - list->addItem(new tsl::elm::CategoryHeader("Chase", true)); - - list->addItem(createBitFlagOption(&menu.LEDGE_STATE, "Ledge Options", ledge_help, this)); - list->addItem(createBitFlagOption(&menu.LEDGE_DELAY, "Ledge Delay", ledge_delay_help, this)); - list->addItem(createBitFlagOption(&menu.TECH_STATE, "Tech Options", tech_help, this)); - list->addItem(createBitFlagOption(&menu.MISS_TECH_STATE, "Missed Tech Options", miss_tech_help, this)); - list->addItem(createBitFlagOption(&menu.DEFENSIVE_STATE, "Defensive Options", defensive_help, this)); - - list->addItem(new tsl::elm::CategoryHeader("Aerials", true)); - - list->addItem(createBitFlagOption(&menu.FAST_FALL, "Fast Fall", fast_fall_help, this)); - list->addItem(createBitFlagOption(&menu.FAST_FALL_DELAY, "Fast Fall Delay", fast_fall_delay_help, this)); - list->addItem(createBitFlagOption(&menu.FALLING_AERIALS, "Falling Aerials", falling_aerials_help, this)); - list->addItem(createBitFlagOption(&menu.AERIAL_DELAY, "Aerial Delay", aerial_delay_help, this)); - list->addItem(createBitFlagOption(&menu.FULL_HOP, "Full Hop", full_hop_help, this)); - - list->addItem(new tsl::elm::CategoryHeader("Miscellaneous", true)); - - list->addItem(new BitFlagToggleListItem( - "Hitbox Visualization", OnOffFlag::On, &menu.HITBOX_VIS, "Hitbox Visualization", hitbox_help)); - - list->addItem(new BitFlagToggleListItem( - "Stage Hazards", OnOffFlag::On, &menu.STAGE_HAZARDS, "Stage Hazards", hazards_help)); - - ClickableListItem* saveStateItem = - new ClickableListItem("Save States", empty_items, nullptr, "saveStates", 0, "Save States", save_states_help); - saveStateItem->setClickListener([](std::vector values, - int* curValue, - std::string extdata, - int index, - std::string title, - std::string help) { tsl::changeTo(title, help); }); - saveStateItem->setHelpListener([](std::string title, std::string help) { tsl::changeTo(title, help); }); - list->addItem(saveStateItem); - - list->addItem(new BitFlagToggleListItem( - "Save Damage", OnOffFlag::On, &menu.SAVE_DAMAGE, "Save Damage", save_damage_help)); - - ValueListItem* inputDelayItem = - new ValueListItem("Input Delay", input_delay_items, &menu.INPUT_DELAY, "inputDelay", input_delay_help); - list->addItem(inputDelayItem); - valueListItems.push_back(inputDelayItem); - - ClickableListItem* resetMenuItem = - new ClickableListItem("Reset Menu", empty_items, nullptr, "resetMenu", 0, "Reset Menu", reset_menu_help); - resetMenuItem->setClickListener([](std::vector values, - int* curValue, - std::string extdata, - int index, - std::string title, - std::string help) { - menu = defaultMenu; - - /* Open Sd card filesystem. */ - FsFileSystem fsSdmc; - if(R_FAILED(fsOpenSdCardFileSystem(&fsSdmc))) return; - tsl::hlp::ScopeGuard fsGuard([&] { fsFsClose(&fsSdmc); }); - - fsFsDeleteFile(&fsSdmc, TRAINING_MOD_CONF); - - tsl::goBack(); - }); - resetMenuItem->setHelpListener([](std::string title, std::string help) { tsl::changeTo(title, help); }); - list->addItem(resetMenuItem); - - rootFrame->setContent(list); - } - else - { - tsl::elm::Element* warning = - new tsl::elm::CustomDrawer([](tsl::gfx::Renderer* renderer, u16 x, u16 y, u16 w, u16 h) { - renderer->drawString("\uE150", false, 180, 250, 90, tsl::Color(255, 255, 255, 255)); - renderer->drawString("Could not debug process memory", false, 110, 340, 25, tsl::Color(255, 255, 255, 255)); - }); - - rootFrame->setContent(warning); - } - } - else - { - tsl::elm::Element* warning = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer* renderer, u16 x, u16 y, u16 w, u16 h) { - renderer->drawString("\uE150", false, 180, 250, 90, tsl::Color(255, 255, 255, 255)); - renderer->drawString("Smash not running.", false, 110, 340, 25, tsl::Color(255, 255, 255, 255)); - }); - - rootFrame->setContent(warning); - } - - return rootFrame; -} - -void GuiMain::update() -{ - static u32 counter = 0; - - if(counter++ % 15 != 0) return; - - applyChanges(); -} - -void GuiMain::applyChanges() -{ - for(ValueListItem* item : valueListItems) - { - item->applyChanges(); - } - Result rc; - Handle debug; - - if(pidSmash != 0) - { - rc = svcDebugActiveProcess(&debug, pidSmash); - if(R_SUCCEEDED(rc)) - { - u64 menu_addr = 0; - FsFile menuAddrFile; - rc = fsFsOpenFile(&this->m_fs, TRAINING_MOD_LOG, FsOpenMode_Read, &menuAddrFile); - if(R_FAILED(rc)) - { - svcCloseHandle(debug); - return; - } - - char buffer[100]; - u64 bytesRead; - rc = fsFileRead(&menuAddrFile, 0, buffer, 100, FsReadOption_None, &bytesRead); - if(R_FAILED(rc)) - { - svcCloseHandle(debug); - return; - } - - fsFileClose(&menuAddrFile); - buffer[bytesRead] = '\0'; - menu_addr = strtoul(buffer, NULL, 16); - - if(menu_addr != 0) - { - rc = svcWriteDebugProcessMemory(debug, &menu, (u64)menu_addr, sizeof(menu)); - } - svcCloseHandle(debug); - } - } - - FsFile menuFile; - fsFsCreateFile(&this->m_fs, TRAINING_MOD_CONF, sizeof(menu), 0); - - rc = fsFsOpenFile(&this->m_fs, TRAINING_MOD_CONF, FsOpenMode_Write, &menuFile); - if(R_FAILED(rc)) - { - fsFileClose(&menuFile); - return; - } - - rc = fsFileWrite(&menuFile, 0, static_cast(&menu), sizeof(menu), FsOpenMode_Write); - if(R_FAILED(rc)) - { - fsFileClose(&menuFile); - return; - } - - fsFileClose(&menuFile); -} \ No newline at end of file diff --git a/TrainingModpackOverlay/source/gui_sublist.cpp b/TrainingModpackOverlay/source/gui_sublist.cpp deleted file mode 100644 index 43a50309..00000000 --- a/TrainingModpackOverlay/source/gui_sublist.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "gui_sublist.hpp" -#include "overflow_list.hpp" -#include "overlay_frame_with_help.hpp" -#include "gui_help.hpp" -#include "clickable_list_item.hpp" -#include "taunt_toggles.hpp" - -GuiSublist::GuiSublist(std::vector menuItems, int* index, std::string extData, std::string title, std::string help) -{ - this->menuItems = menuItems; - this->index = index; - this->extData = extData; - this->title = title; - this->help = help; -} - -GuiSublist::~GuiSublist() {} - -tsl::elm::Element* GuiSublist::createUI() -{ - tsl::elm::OverlayFrame* rootFrame = new OverlayFrameWithHelp(title, "Press \uE0E3 for help with these options."); - - auto list = new OverflowList(); - - for(size_t i = 0; i < menuItems.size(); i++) - { - auto item = new ClickableListItem(menuItems[i], menuItems, this->index, "", i, title, help); - setClickListener(item); - item->setHelpListener([](std::string title, std::string help) { tsl::changeTo(title, help); }); - list->addItem(item); - listItems.push_back(item); - } - - list->setFocusedIndex(*index); - - rootFrame->setContent(list); - - return rootFrame; -} - -void GuiSublist::setClickListener(ClickableListItem* item) -{ - item->setClickListener([](std::vector values, - int* curValue, - std::string extdata, - int index, - std::string title, - std::string help) { - *curValue = index; - tsl::goBack(); - }); -} - -void GuiSublist::update() -{ - static u32 counter = 0; - - if(counter++ % 15 != 0) return; - - applyChanges(); -} - -void GuiSublist::applyChanges() {} \ No newline at end of file diff --git a/TrainingModpackOverlay/source/main.cpp b/TrainingModpackOverlay/source/main.cpp deleted file mode 100644 index 092e2f3c..00000000 --- a/TrainingModpackOverlay/source/main.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#define TESLA_INIT_IMPL -#include "gui_main.hpp" - -class TrainingModpackOverlay : public tsl::Overlay -{ -public: - TrainingModpackOverlay() {} - ~TrainingModpackOverlay() {} - - void initServices() override { pmshellInitialize(); } - - void exitServices() override { pmshellExit(); } - - std::unique_ptr loadInitialGui() override { return std::make_unique(); } -}; - -int main(int argc, char** argv) -{ - return tsl::loop(argc, argv); -} \ No newline at end of file diff --git a/src/common/consts.rs b/src/common/consts.rs index cec6fe3d..f2a2bc00 100644 --- a/src/common/consts.rs +++ b/src/common/consts.rs @@ -3,56 +3,66 @@ use core::f64::consts::PI; use smash::lib::lua_const::*; // bitflag helper function macro -macro_rules! to_vec_impl { +macro_rules! extra_bitflag_impls { ($e:ty) => { - pub fn to_vec(&self) -> Vec::<$e> { - let mut vec = Vec::<$e>::new(); - let mut field = <$e>::from_bits_truncate(self.bits); - while !field.is_empty() { - let flag = <$e>::from_bits(1u32 << field.bits.trailing_zeros()).unwrap(); - field -= flag; - vec.push(flag); + impl core::fmt::Display for $e { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + core::fmt::Debug::fmt(self, f) + } + } + + impl $e { + pub fn to_vec(&self) -> Vec::<$e> { + let mut vec = Vec::<$e>::new(); + let mut field = <$e>::from_bits_truncate(self.bits); + while !field.is_empty() { + let flag = <$e>::from_bits(1u32 << field.bits.trailing_zeros()).unwrap(); + field -= flag; + vec.push(flag); + } + return vec; + } + + pub fn to_index(&self) -> u32 { + if self.bits == 0 { + return 0; + } + + return self.bits.trailing_zeros(); + } + + pub fn get_random(&self) -> $e { + let options = self.to_vec(); + match options.len() { + 0 => { + return <$e>::empty(); + } + 1 => { + return options[0]; + } + _ => { + return *random_option(&options); + } + } + } + + pub fn to_toggle_strs() -> Vec { + let all_options = <$e>::all().to_vec(); + all_options.iter().map(|i| i.into_string()).collect() + } + + pub fn to_toggle_vals() -> Vec { + let all_options = <$e>::all().to_vec(); + all_options.iter().map(|i| i.bits() as usize).collect() } - return vec; } } } -macro_rules! to_index_impl { - ($e:ty) => { - pub fn to_index(&self) -> u32 { - if self.bits == 0 { - return 0; - } - - return self.bits.trailing_zeros(); - } - }; -} - pub fn random_option(arg: &[T]) -> &T { &arg[get_random_int(arg.len() as i32) as usize] } -macro_rules! get_random_impl { - ($e:ty) => { - pub fn get_random(&self) -> $e { - let options = self.to_vec(); - match options.len() { - 0 => { - return <$e>::empty(); - } - 1 => { - return options[0]; - } - _ => { - return *random_option(&options); - } - } - } - }; -} - // DI /* 0, 0.785398, 1.570796, 2.356194, -3.14159, -2.356194, -1.570796, -0.785398 @@ -98,10 +108,24 @@ impl Direction { _ => 0, } } - to_vec_impl! {Direction} - get_random_impl! {Direction} + + fn into_string(self) -> String { + match self { + Direction::OUT => "Away", + Direction::UP_OUT => "Up and Away", + Direction::UP => "Up", + Direction::UP_IN => "Up and In", + Direction::IN => "In", + Direction::DOWN_IN => "Down and In", + Direction::DOWN => "Down", + Direction::DOWN_OUT => "Down and Away", + _ => "", + }.to_string() + } } +extra_bitflag_impls! {Direction} + // Ledge Option bitflags! { pub struct LedgeOption : u32 @@ -125,10 +149,21 @@ impl LedgeOption { _ => return None, }) } - to_vec_impl! {LedgeOption} - get_random_impl! {LedgeOption} + + fn into_string(self) -> String { + match self { + LedgeOption::NEUTRAL => "Neutral Getup", + LedgeOption::ROLL => "Roll", + LedgeOption::JUMP => "Jump", + LedgeOption::ATTACK => "Getup Attack", + LedgeOption::WAIT => "Wait", + _ => "", + }.to_string() + } } +extra_bitflag_impls! {LedgeOption} + // Tech options bitflags! { pub struct TechFlags : u32 { @@ -140,10 +175,19 @@ bitflags! { } impl TechFlags { - to_vec_impl! {TechFlags} - get_random_impl! {TechFlags} + fn into_string(self) -> String { + match self { + TechFlags::NO_TECH => "No Tech", + TechFlags::ROLL_F => "Roll Forwards", + TechFlags::ROLL_B => "Roll Backwards", + TechFlags::IN_PLACE => "Tech In Place", + _ => "", + }.to_string() + } } +extra_bitflag_impls! {TechFlags} + // Missed Tech Options bitflags! { pub struct MissTechFlags : u32 { @@ -155,13 +199,22 @@ bitflags! { } impl MissTechFlags { - to_vec_impl! {MissTechFlags} - get_random_impl! {MissTechFlags} + fn into_string(self) -> String { + match self { + MissTechFlags::GETUP => "Neutral Getup", + MissTechFlags::ATTACK => "Getup Attack", + MissTechFlags::ROLL_F => "Roll Forwards", + MissTechFlags::ROLL_B => "Roll Backwards", + _ => "", + }.to_string() + } } +extra_bitflag_impls! {MissTechFlags} + /// Shield States #[repr(i32)] -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, FromPrimitive)] pub enum Shield { None = 0, Infinite = 1, @@ -169,6 +222,18 @@ pub enum Shield { Constant = 3, } +impl Shield { + fn into_string(self) -> String { + match self { + Shield::None => "None", + Shield::Infinite => "Infinite", + Shield::Hold => "Hold", + Shield::Constant => "Constant", + _ => "", + }.to_string() + } +} + // Defensive States bitflags! { pub struct Defensive : u32 { @@ -181,10 +246,20 @@ bitflags! { } impl Defensive { - to_vec_impl! {Defensive} - get_random_impl! {Defensive} + fn into_string(self) -> String { + match self { + Defensive::SPOT_DODGE => "Spotdodge", + Defensive::ROLL_F => "Roll Forwards", + Defensive::ROLL_B => "Roll Backwards", + Defensive::JAB => "Jab", + Defensive::SHIELD => "Shield", + _ => "", + }.to_string() + } } +extra_bitflag_impls! {Defensive} + #[repr(i32)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum OnOff { @@ -192,6 +267,24 @@ pub enum OnOff { On = 1, } +impl OnOff { + pub fn from_val(val: u32) -> Option { + match val { + 1 => Some(OnOff::On), + 0 => Some(OnOff::Off), + _ => None + } + } + + pub fn into_string(self) -> String { + match self { + OnOff::Off => "Off", + OnOff::On => "On", + _ => "" + }.to_string() + } +} + bitflags! { pub struct Action : u32 { const AIR_DODGE = 0x1; @@ -234,10 +327,15 @@ impl Action { _ => return None, }) } - to_vec_impl! {Action} - get_random_impl! {Action} + + pub fn into_string(self) -> String { + // TODO: add + return self.to_string() + } } +extra_bitflag_impls! {Action} + bitflags! { pub struct AttackAngle : u32 { const NEUTRAL = 0x1; @@ -247,10 +345,14 @@ bitflags! { } impl AttackAngle { - to_vec_impl! {AttackAngle} - get_random_impl! {AttackAngle} + pub fn into_string(self) -> String { + // TODO: add + return self.to_string() + } } +extra_bitflag_impls! {AttackAngle} + bitflags! { pub struct Delay : u32 { @@ -289,11 +391,14 @@ bitflags! { } impl Delay { - to_vec_impl! {Delay} - get_random_impl! {Delay} - to_index_impl! {Delay} + pub fn into_string(self) -> String { + // TODO: add + return self.to_string() + } } +extra_bitflag_impls! {Delay} + bitflags! { pub struct BoolFlag : u32 { const TRUE = 0x1; @@ -301,16 +406,20 @@ bitflags! { } } -impl BoolFlag { - to_vec_impl! {BoolFlag} - get_random_impl! {BoolFlag} +extra_bitflag_impls! {BoolFlag} +impl BoolFlag { pub fn into_bool(self) -> bool { match self { BoolFlag::TRUE => true, _ => false, } } + + pub fn into_string(self) -> String { + // TODO: add + return self.to_string() + } } #[repr(C)] @@ -343,6 +452,50 @@ pub struct TrainingModpackMenu { pub save_damage: OnOff, } +macro_rules! set_by_str { + ($obj:ident, $s:ident, $(($field:ident = $rhs:expr))*) => { + $( + if $s == stringify!($field) { + $obj.$field = $rhs.unwrap(); + } + )* + } +} + +impl TrainingModpackMenu { + pub fn set(&mut self, s: &str, val: u32) { + set_by_str!(self, s, + (di_state = Direction::from_bits(val)) + (sdi_state = Direction::from_bits(val)) + (air_dodge_dir = Direction::from_bits(val)) + + (mash_state = Action::from_bits(val)) + (follow_up = Action::from_bits(val)) + + (ledge_state = LedgeOption::from_bits(val)) + (ledge_delay = Delay::from_bits(val)) + (tech_state = TechFlags::from_bits(val)) + (miss_tech_state = MissTechFlags::from_bits(val)) + + (shield_state = num::FromPrimitive::from_u32(val)) + (defensive_state = Defensive::from_bits(val)) + (oos_offset = Delay::from_bits(val)) + (reaction_time = Delay::from_bits(val)) + + (fast_fall = BoolFlag::from_bits(val)) + (fast_fall_delay = Delay::from_bits(val)) + (falling_aerials = BoolFlag::from_bits(val)) + (aerial_delay = Delay::from_bits(val)) + (full_hop = BoolFlag::from_bits(val)) + + (hitbox_vis = OnOff::from_val(val)) + (stage_hazards = OnOff::from_val(val)) + + (input_delay = Some(val as i32)) + ); + } +} + // Fighter Ids #[repr(i32)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -368,4 +521,9 @@ impl SdiStrength { SdiStrength::High => 4, } } + + pub fn into_string(self) -> String { + // TODO: add + return "".to_string() + } } \ No newline at end of file diff --git a/src/common/menu.rs b/src/common/menu.rs new file mode 100644 index 00000000..0ce4c386 --- /dev/null +++ b/src/common/menu.rs @@ -0,0 +1,291 @@ + + +use crate::common::*; +use skyline::nn::hid::NpadHandheldState; +use smash::lib::lua_const::*; + +use skyline_web::{Background, BootDisplay, Webpage}; +use ramhorns::{Template, Content}; + +#[derive(Content)] +struct Slider { + min: usize, + max: usize, + index: usize, + value: usize +} + +#[derive(Content)] +struct Toggle<'a> { + title: &'a str, + checked: &'a str, + index: usize, + value: usize, +} + +impl<'a> Toggle<'a> { + pub fn new(title: &'a str, checked: bool, value: usize) -> Toggle<'a> { + Toggle{ + title: title, + checked: if checked { "is-appear "} else { "is-hidden" }, + index: 0, + value + } + } +} + +#[derive(Content)] +struct SubMenu<'a> { + title: &'a str, + id: &'a str, + toggles: Vec>, + sliders: Vec, + index: usize, + check_against: usize +} + +impl<'a> SubMenu<'a> { + pub fn max_idx(&self) -> usize { + self.toggles + .iter() + .max_by(|t1,t2| t1.index.cmp(&t2.index)) + .map(|t| t.index) + .unwrap_or(self.index) + } + + pub fn add_toggle(&mut self, title: &'a str, checked: bool, value: usize) { + self.toggles.push(Toggle{ + title: title, + checked: if checked { "is-appear "} else { "is-hidden" }, + index: self.max_idx() + 1, + value + }); + } + + pub fn add_slider(&mut self, min: usize, max: usize, value: usize) { + self.sliders.push(Slider{ + min, + max, + index: self.max_idx() + 1, + value + }); + } +} + +#[derive(Content)] +struct Menu<'a> { + sub_menus: Vec> +} + +impl<'a> Menu<'a> { + pub fn max_idx(&self) -> usize { + self.sub_menus + .iter() + .max_by(|x, y| x.max_idx().cmp(&y.max_idx())) + .map(|sub_menu| sub_menu.max_idx()) + .unwrap_or(0) + } + + pub fn add_sub_menu(&mut self, title: &'a str, id: &'a str, check_against: usize, toggles: Vec<(&'a str, usize)>, sliders: Vec<(usize,usize,usize)>) { + let mut sub_menu = SubMenu { + title: title, + id: id, + toggles: Vec::new(), + sliders: Vec::new(), + index: self.max_idx() + 1, + check_against: check_against + }; + + for toggle in toggles { + sub_menu.add_toggle(toggle.0, (check_against & toggle.1) != 0, toggle.1) + } + + for slider in sliders { + sub_menu.add_slider(slider.0, slider.1, slider.2); + } + + self.sub_menus.push(sub_menu); + } + + pub fn add_sub_menu_sep(&mut self, title: &'a str, id: &'a str, check_against: usize, strs: Vec<&'a str>, vals: Vec) { + let mut sub_menu = SubMenu { + title: title, + id: id, + toggles: Vec::new(), + sliders: Vec::new(), + index: self.max_idx() + 1, + check_against: check_against + }; + + for i in 0..strs.len() { + sub_menu.add_toggle(strs[i], (check_against & vals[i]) != 0, vals[i]) + } + + // TODO: add sliders? + + self.sub_menus.push(sub_menu); + } +} + +macro_rules! add_bitflag_submenu { + ($menu:ident, $title:literal, $id:ident, $e:ty) => { + paste::paste!{ + let [<$id _strs>] = <$e>::to_toggle_strs(); + let [<$id _vals>] = <$e>::to_toggle_vals(); + + $menu.add_sub_menu_sep( + $title, + stringify!($id), + MENU_STRUCT.$id.bits() as usize, + [<$id _strs>].iter().map(|i| i.as_str()).collect(), + [<$id _vals>] + ); + } + } +} + +pub fn set_menu_from_url(s: &str) { + let base_url_len = "http://localhost/".len(); + let total_len = s.len(); + + let ss: String = s.chars().skip(base_url_len).take(total_len - base_url_len).collect(); + + for toggle_values in ss.split("&") { + let toggle_value_split = toggle_values.split("?").collect::>(); + let toggle = toggle_value_split[0]; + if toggle == "" { continue; } + + let toggle_vals = toggle_value_split[1]; + + let mut bits = 0; + for toggle_val in toggle_vals.split(",") { + if toggle_val == "" { continue; } + + let mut val = toggle_val.parse::().unwrap(); + bits = bits | val; + } + + + unsafe { + MENU_STRUCT.set(toggle, bits); + } + } +} + +pub unsafe fn menu_condition(module_accessor: &mut smash::app::BattleObjectModuleAccessor) -> bool { + ControlModule::check_button_on(module_accessor, *CONTROL_PAD_BUTTON_SPECIAL) && + ControlModule::check_button_on_trriger(module_accessor, *CONTROL_PAD_BUTTON_APPEAL_HI) +} + +pub unsafe fn render_menu() -> String { + let tpl = Template::new(include_str!("../templates/menu.html")).unwrap(); + + let mut overall_menu = Menu { + sub_menus: Vec::new() + }; + + // Toggle/bitflag menus + add_bitflag_submenu!(overall_menu, "Mash Toggles", mash_state, Action); + add_bitflag_submenu!(overall_menu, "Followup Toggles", follow_up, Action); + add_bitflag_submenu!(overall_menu, "Attack Angle", attack_angle, AttackAngle); + + add_bitflag_submenu!(overall_menu, "Ledge Options", ledge_state, LedgeOption); + add_bitflag_submenu!(overall_menu, "Ledge Delay", ledge_delay, Delay); + add_bitflag_submenu!(overall_menu, "Tech Options", tech_state, TechFlags); + add_bitflag_submenu!(overall_menu, "Miss Tech Options", miss_tech_state, MissTechFlags); + add_bitflag_submenu!(overall_menu, "Defensive Options", defensive_state, Defensive); + + add_bitflag_submenu!(overall_menu, "OoS Offset", oos_offset, Delay); + add_bitflag_submenu!(overall_menu, "Reaction Time", reaction_time, Delay); + + add_bitflag_submenu!(overall_menu, "Fast Fall", fast_fall, BoolFlag); + add_bitflag_submenu!(overall_menu, "Fast Fall Delay", fast_fall_delay, Delay); + add_bitflag_submenu!(overall_menu, "Falling Aerials", falling_aerials, BoolFlag); + add_bitflag_submenu!(overall_menu, "Full Hop", full_hop, BoolFlag); + + add_bitflag_submenu!(overall_menu, "Shield Tilt", shield_tilt, Direction); + + add_bitflag_submenu!(overall_menu, "DI", di_state, Direction); + add_bitflag_submenu!(overall_menu, "SDI", sdi_state, Direction); + add_bitflag_submenu!(overall_menu, "Airdodge Direction", air_dodge_dir, Direction); + + overall_menu.add_sub_menu( + "Shield Toggles", + "shield_state", + MENU_STRUCT.shield_state as usize, + [ + ("None", Shield::None as usize), + ("Hold", Shield::Hold as usize), + ("Infinite", Shield::Infinite as usize), + ].to_vec(), + [].to_vec() + ); + + // Slider menus + overall_menu.add_sub_menu( + "Input Delay", + "input_delay", + // unnecessary for slider? + MENU_STRUCT.input_delay as usize, + [].to_vec(), + [ + (0, 10, MENU_STRUCT.input_delay as usize) + ].to_vec() + ); + + // SDI strength + + + // TODO: OnOff flags... need a different sort of submenu. + overall_menu.add_sub_menu( + "Hitbox Visualization", + "hitbox_vis", + MENU_STRUCT.hitbox_vis as usize, + [ + ("Off", OnOff::Off as usize), + ("On", OnOff::On as usize), + ].to_vec(), + [].to_vec() + ); + overall_menu.add_sub_menu( + "Stage Hazards", + "stage_hazards", + MENU_STRUCT.stage_hazards as usize, + [ + ("Off", OnOff::Off as usize), + ("On", OnOff::On as usize), + ].to_vec(), + [].to_vec() + ); + overall_menu.add_sub_menu( + "Mash In Neutral", + "mash_in_neutral", + MENU_STRUCT.mash_in_neutral as usize, + [ + ("Off", OnOff::Off as usize), + ("On", OnOff::On as usize), + ].to_vec(), + [].to_vec() + ); + + + + tpl.render(&overall_menu) +} + +pub unsafe fn spawn_menu() { + let data = render_menu(); + + let response = Webpage::new() + .background(Background::BlurredScreenshot) + .file("index.html", &data) + .htdocs_dir("contents") + .boot_display(BootDisplay::BlurredScreenshot) + .boot_icon(true) + .open() + .unwrap(); + + let last_url = response.get_last_url().unwrap(); + + set_menu_from_url(last_url); +} diff --git a/src/common/mod.rs b/src/common/mod.rs index 751bede4..1bdfccd5 100644 --- a/src/common/mod.rs +++ b/src/common/mod.rs @@ -1,4 +1,5 @@ pub mod consts; +pub mod menu; use crate::common::consts::*; use smash::app::{self, lua_bind::*}; diff --git a/src/lib.rs b/src/lib.rs index 177df788..aac4cc97 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,14 +2,20 @@ #![feature(with_options)] #![feature(const_mut_refs)] -mod common; +pub mod common; mod hazard_manager; mod hitbox_visualizer; mod training; +#[cfg(test)] +mod test; + #[macro_use] extern crate bitflags; +#[macro_use] +extern crate num_derive; + use crate::common::*; use training::combo::FRAME_ADVANTAGE; @@ -39,6 +45,7 @@ macro_rules! c_str { }; } +#[cfg(not(test))] #[skyline::main(name = "training_modpack")] pub fn main() { macro_rules! log { @@ -92,4 +99,4 @@ pub fn main() { fclose(f); } } -} +} \ No newline at end of file diff --git a/src/templates/check.svg b/src/templates/check.svg new file mode 100644 index 00000000..860937cc --- /dev/null +++ b/src/templates/check.svg @@ -0,0 +1,8 @@ + + + + + + + diff --git a/src/templates/frame_adv.webp b/src/templates/frame_adv.webp new file mode 100644 index 00000000..5cffa7e4 Binary files /dev/null and b/src/templates/frame_adv.webp differ diff --git a/src/templates/menu.html b/src/templates/menu.html new file mode 100644 index 00000000..1448c354 --- /dev/null +++ b/src/templates/menu.html @@ -0,0 +1,221 @@ + + + + + + + Document + + + + + + + + + + + + + + + + + +
+
+
+
+ + + {{#sub_menus}} +
+ +
+
+
+ +

{{title}}

+
+
+
+
+ +
+ {{/sub_menus}} + {{#sub_menus}} + {{#sliders}} + + {{/sliders}} + {{/sub_menus}} + + + + \ No newline at end of file diff --git a/src/templates/slider.js b/src/templates/slider.js new file mode 100644 index 00000000..37d30f14 --- /dev/null +++ b/src/templates/slider.js @@ -0,0 +1,77 @@ +var slider = document.getElementById('slider'); +const STEP = 5 + +function checkGamepad(index, gamepad) { + // Gets the current value of the sliders + var current_value = slider.noUiSlider.get(); + + // Displays it on the HTML page + document.getElementById("input").innerHTML = current_value; + + + // Checks to see if the L-button is pressed + if(gamepad.buttons[4].pressed){ + // If the right-side of the slider is focused on, subtract STEP from the current value + if(document.activeElement.classList.contains("noUi-handle-upper")){ + slider.noUiSlider.set( + [ + null, + parseInt(current_value[1]) - STEP + ]); + } + // If the left-side of the slider is focused on, subtract STEP from the current value + else if(document.activeElement.classList.contains("noUi-handle-lower")){ + slider.noUiSlider.set( + [ + parseInt(current_value[0]) - STEP, + null + ]); + } + } + // Checks to see if the R-button is pressed + else if(gamepad.buttons[5].pressed){ + // If the right-side of the slider is focused on, add STEP to the current value + if(document.activeElement.classList.contains("noUi-handle-upper")){ + slider.noUiSlider.set( + [ + null, + parseInt(current_value[1]) + STEP + ]); + } + // If the left-side of the slider is focused on, add STEP to the current value + else if(document.activeElement.classList.contains("noUi-handle-lower")){ + slider.noUiSlider.set( + [ + parseInt(current_value[0]) + STEP, + null + ]); + } + } +}; + +window.onload = function(){ + // Creates the slider + noUiSlider.create(slider, { + start: [20, 80], + connect: true, + range: { + 'min': 0, + 'max': 100 + } + }); + + // Listens to see if the gamepad is connected + window.addEventListener("gamepadconnected", function (e) { + document.getElementById("input").innerHTML = "Gamepad Connected!"; + }); + + // Sets an interval and runs a function every 100 seconds to check the gamepads + setInterval(function () { + var gpl = navigator.getGamepads(); + if (gpl.length > 0) { + for (var i = 0; i < gpl.length; i++) { + checkGamepad(i, gpl[i]); + } + } + }, 100); +} \ No newline at end of file diff --git a/src/test.rs b/src/test.rs new file mode 100644 index 00000000..72420d9e --- /dev/null +++ b/src/test.rs @@ -0,0 +1,30 @@ +/// Recommended to run with the following command: +/// `RUSTFLAGS=-Awarnings cargo test --target=x86_64-unknown-linux-gnu` +/// But you can replace the target with your PC's target. + +/// This will run and render the default menu in your default HTML opening program, ideally Chrome. +#[test] +fn render_menu() { + unsafe { + use std::process::Command; + use crate::common::menu::render_menu; + + let folder_path = "../contents.htdocs"; + let path = "../contents.htdocs/index.html"; + + assert!(std::path::Path::new(folder_path).exists(), "Needs required folder: ../contents.htdocs!"); + + std::fs::write(path, render_menu()).unwrap(); + + let (cmd, args) = if wsl::is_wsl() || cfg!(target_os = "windows") { + ("cmd.exe", ["/C", "start", path]) + } else { + ("sh", ["-c", "open", path]) + }; + + Command::new(cmd) + .args(&args) + .output() + .expect("failed to open rendered HTML file"); + } +} \ No newline at end of file diff --git a/src/training/mod.rs b/src/training/mod.rs index acf95fb9..eb523f8a 100644 --- a/src/training/mod.rs +++ b/src/training/mod.rs @@ -98,6 +98,10 @@ fn once_per_frame_per_fighter( } unsafe { + if crate::common::menu::menu_condition(module_accessor) { + crate::common::menu::spawn_menu(); + } + input_record::get_command_flag_cat(module_accessor); combo::get_command_flag_cat(module_accessor); hitbox_visualizer::get_command_flag_cat(module_accessor);