diff --git a/.ci/switch/buildswitch.bash b/.ci/switch/buildswitch.bash
new file mode 100755
index 000000000..032b19157
--- /dev/null
+++ b/.ci/switch/buildswitch.bash
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+cp -av /usr/local/lib/libSDL2* /lib/x86_64-linux-gnu/
+git config --global --add safe.directory /soh
+make setup -C soh -j$(nproc) OPTFLAGS=-O2 DEBUG=0 CC="gcc" CXX="g++"
+
+/opt/devkitpro/portlibs/switch/bin/aarch64-none-elf-cmake -B StormLib/build-switch -S StormLib -DCMAKE_INSTALL_PREFIX=/opt/devkitpro/portlibs/switch/
+make -C StormLib/build-switch -j$(nproc)
+make install -C StormLib/build-switch
+
+make -f Makefile.switch -j$(nproc) OPTFLAGS=-O2 DEBUG=0
diff --git a/.gitignore b/.gitignore
index 5f9933097..e4e07589b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -407,6 +407,13 @@ oot.otr
shipofharkinian.ini
shipofharkinian.json
+# Switch Stuff
+
+*.nro
+*.nacp
+ZAPDTR/ZAPDUtils/lib/*
+!/soh/icon.jpg
+
# Xcode
xcuserdata/
*.xcconfig
diff --git a/Dockerfile.switch b/Dockerfile.switch
new file mode 100644
index 000000000..7319f22a6
--- /dev/null
+++ b/Dockerfile.switch
@@ -0,0 +1,58 @@
+FROM ubuntu:20.04 as build
+
+ENV LANG C.UTF-8
+ARG DEBIAN_FRONTEND=noninteractive
+
+ENV GCCVER=10
+RUN \
+ apt-get update && \
+ apt-get upgrade -y && \
+ apt-get install -y \
+ binutils \
+ gcc-10 \
+ g++-10 \
+ p7zip-full \
+ python3 \
+ make \
+ cmake \
+ curl \
+ git \
+ lld \
+ wget \
+ libsdl2-dev \
+ zlib1g-dev \
+ libbz2-dev \
+ libpng-dev \
+ libgles2-mesa-dev && \
+ update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCCVER} 10 && \
+ update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCCVER} 10
+
+RUN git clone https://github.com/Perlmint/glew-cmake.git && \
+ cmake glew-cmake && \
+ make -j$(nproc) && \
+ make install ARCH64=true
+
+ENV SDL2VER=2.0.22
+RUN curl -sLO https://libsdl.org/release/SDL2-${SDL2VER}.tar.gz && \
+ tar -xzf SDL2-${SDL2VER}.tar.gz && \
+ cd SDL2-${SDL2VER} && \
+ ./configure --build=x86_64-linux-gnu && \
+ make && make install && \
+ rm ../SDL2-${SDL2VER}.tar.gz
+
+RUN \
+ ln -sf /proc/self/mounts /etc/mtab && \
+ mkdir -p /usr/local/share/keyring/ && \
+ wget -O /usr/local/share/keyring/devkitpro-pub.gpg https://apt.devkitpro.org/devkitpro-pub.gpg && \
+ echo "deb [signed-by=/usr/local/share/keyring/devkitpro-pub.gpg] https://apt.devkitpro.org stable main" > /etc/apt/sources.list.d/devkitpro.list && \
+ apt-get update -y && \
+ apt-get install -y devkitpro-pacman && \
+ yes | dkp-pacman -Syu switch-dev switch-portlibs --noconfirm
+
+ENV DEVKITPRO=/opt/devkitpro
+ENV DEVKITARM=/opt/devkitpro/devkitARM
+ENV DEVKITPPC=/opt/devkitpro/devkitPPC
+ENV PATH=$PATH:/opt/devkitpro/portlibs/switch/bin/
+
+RUN mkdir /soh
+WORKDIR /soh
diff --git a/Jenkinsfile b/Jenkinsfile
index f9ac7e7c8..033f1f758 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -106,9 +106,9 @@ pipeline {
mv OTRGui/build/assets build/
mv ZAPDTR/ZAPD.out build/assets/extractor/
mv README.md readme.txt
-
+
docker exec sohcont appimage/appimage.sh
-
+
7z a soh-linux.7z SOH-Linux.AppImage readme.txt
'''
@@ -158,7 +158,47 @@ pipeline {
}
}
}
+ stage ('Build Switch') {
+ options {
+ timeout(time: 20)
+ }
+ agent {
+ label "SoH-Linux-Builders"
+ }
+ steps {
+ checkout([
+ $class: 'GitSCM',
+ branches: scm.branches,
+ doGenerateSubmoduleConfigurations: scm.doGenerateSubmoduleConfigurations,
+ extensions: scm.extensions,
+ userRemoteConfigs: scm.userRemoteConfigs
+ ])
+ catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
+ sh '''
+
+ cp ../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64
+ docker build . -t sohswitch -f Dockerfile.switch
+ docker run --name sohcont -dit --rm -v $(pwd):/soh sohswitch /bin/bash
+ docker exec sohcont .ci/switch/buildswitch.bash
+
+ mv soh/soh.nro .
+ mv README.md readme.txt
+
+ 7z a soh-switch.7z soh.nro readme.txt
+
+ '''
+ }
+ sh 'sudo docker container stop sohcont'
+ archiveArtifacts artifacts: 'soh-switch.7z', followSymlinks: false, onlyIfSuccessful: true
+ }
+ post {
+ always {
+ step([$class: 'WsCleanup']) // Clean workspace
+ }
+ }
+ }
}
}
}
}
+
diff --git a/Makefile.switch b/Makefile.switch
new file mode 100644
index 000000000..2dd9f5ea2
--- /dev/null
+++ b/Makefile.switch
@@ -0,0 +1,36 @@
+#-------------------------------------------------------------------------------
+.SUFFIXES:
+#-------------------------------------------------------------------------------
+
+export SOH_TOP_DIR := $(CURDIR)
+
+.PHONY: all clean ZAPDUtils libultraship soh StormLib
+
+all: soh
+ @echo "Done!"
+
+ZAPDUtils:
+ @echo "Building $@..."
+ @$(MAKE) --no-print-directory -C $(CURDIR)/ZAPDTR/ZAPDUtils -f $(CURDIR)/ZAPDTR/ZAPDUtils/Makefile.switch
+
+StormLib:
+ @echo "Building $@..."
+ LDFLAGS="" ${DEVKITPRO}/portlibs/switch/bin/aarch64-none-elf-cmake -DCMAKE_TOOLCHAIN_FILE=${DEVKITPRO}/cmake/Switch.cmake -DCMAKE_BUILD_TYPE=Release -B $(CURDIR)/StormLib/nxbuild -S $(CURDIR)/StormLib
+ @$(MAKE) --no-print-directory -C $(CURDIR)/StormLib/nxbuild -f $(CURDIR)/StormLib/nxbuild/Makefile
+
+libultraship: StormLib ZAPDUtils
+ @echo "Building $@..."
+ @$(MAKE) --no-print-directory -C $(CURDIR)/libultraship -f $(CURDIR)/libultraship/Makefile.switch
+
+soh: libultraship
+ @echo "Building $@..."
+ @$(MAKE) --no-print-directory -C $(CURDIR)/soh -f $(CURDIR)/soh/Makefile.switch
+
+otr:
+ @echo "Building $@..."
+ @$(MAKE) --no-print-directory -C $(CURDIR)/soh -f $(CURDIR)/soh/Makefile setup
+
+clean:
+ @$(MAKE) --no-print-directory -C $(CURDIR)/ZAPDTR/ZAPDUtils -f $(CURDIR)/ZAPDTR/ZAPDUtils/Makefile.switch clean
+ @$(MAKE) --no-print-directory -C $(CURDIR)/libultraship -f $(CURDIR)/libultraship/Makefile.switch clean
+ @$(MAKE) --no-print-directory -C $(CURDIR)/soh -f $(CURDIR)/soh/Makefile.switch clean
\ No newline at end of file
diff --git a/OTRExporter/OTRExporter/OTRExporter.vcxproj b/OTRExporter/OTRExporter/OTRExporter.vcxproj
index cecb9eaf3..c39da3df5 100644
--- a/OTRExporter/OTRExporter/OTRExporter.vcxproj
+++ b/OTRExporter/OTRExporter/OTRExporter.vcxproj
@@ -65,12 +65,6 @@
-
-
- {02d10590-9542-3f55-aaf8-6055677e2a2a}
- false
-
-
16.0
Win32Proj
diff --git a/StormLib/.gitignore b/StormLib/.gitignore
index 3d764df91..660d12e05 100644
--- a/StormLib/.gitignore
+++ b/StormLib/.gitignore
@@ -140,6 +140,7 @@ Desktop.ini
*.egg-info
dist
build
+nxbuild
eggs
parts
bin
diff --git a/StormLib/CMakeLists.txt b/StormLib/CMakeLists.txt
index bef21d8e9..243dea578 100644
--- a/StormLib/CMakeLists.txt
+++ b/StormLib/CMakeLists.txt
@@ -323,6 +323,11 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL FreeBSD)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DO_LARGEFILE=0 -Dstat64=stat -Dlstat64=lstat -Dlseek64=lseek -Doff64_t=off_t -Dfstat64=fstat -Dftruncate64=ftruncate")
endif()
+if(NOT WIN32 AND NOT APPLE AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL FreeBSD)
+ # Enable POSIX extensions such as `readlink` and `ftruncate`.
+ add_definitions(-D_POSIX_C_SOURCE=200809L)
+endif()
+
add_library(${LIBRARY_NAME} ${LIB_TYPE} ${SRC_FILES} ${SRC_ADDITIONAL_FILES} ${STORM_DEF_FILES})
if(WIN32)
set_target_properties(${LIBRARY_NAME} PROPERTIES OUTPUT_NAME "StormLib")
diff --git a/StormLib/src/StormPort.h b/StormLib/src/StormPort.h
index d38641422..77195f88d 100644
--- a/StormLib/src/StormPort.h
+++ b/StormLib/src/StormPort.h
@@ -95,7 +95,7 @@
#define PKEXPORT
- #ifndef __SYS_ZLIB
+ #ifndef __SYS_ZLIB
#define __SYS_ZLIB
#endif
diff --git a/ZAPDTR/ZAPD/ZAPD.vcxproj b/ZAPDTR/ZAPD/ZAPD.vcxproj
index ad3c3e08c..9369e97da 100644
--- a/ZAPDTR/ZAPD/ZAPD.vcxproj
+++ b/ZAPDTR/ZAPD/ZAPD.vcxproj
@@ -359,12 +359,6 @@
-
-
- {02d10590-9542-3f55-aaf8-6055677e2a2a}
- false
-
-
diff --git a/ZAPDTR/ZAPDUtils/Makefile.switch b/ZAPDTR/ZAPDUtils/Makefile.switch
new file mode 100644
index 000000000..ed173c44f
--- /dev/null
+++ b/ZAPDTR/ZAPDUtils/Makefile.switch
@@ -0,0 +1,171 @@
+#---------------------------------------------------------------------------------
+.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.
+#---------------------------------------------------------------------------------
+TARGET := ZAPDUtils
+BUILD := build
+SOURCES := Utils
+DATA :=
+INCLUDES :=
+
+#-------------------------------------------------------------------------------
+# source files
+#-------------------------------------------------------------------------------
+SOURCEFILES_C :=
+
+SOURCEFILES_CPP :=
+
+#---------------------------------------------------------------------------------
+# 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__
+
+CXXFLAGS := $(CFLAGS) -fno-rtti -fexceptions -std=gnu++20
+CFLAGS += -std=gnu11
+
+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)/lib/lib$(TARGET).a
+export TOPDIR := $(CURDIR)
+
+export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
+ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
+ $(foreach sf,$(SOURCEFILES_C),$(CURDIR)/$(dir $(sf))) \
+ $(foreach sf,$(SOURCEFILES_CPP),$(CURDIR)/$(dir $(sf)))
+
+export DEPSDIR := $(CURDIR)/$(BUILD)
+
+CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) \
+ $(foreach f,$(SOURCEFILES_C),$(notdir $(f)))
+CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) \
+ $(foreach f,$(SOURCEFILES_CPP),$(notdir $(f)))
+SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
+BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
+
+#---------------------------------------------------------------------------------
+# use CXX for linking C++ projects, CC for standard C
+#---------------------------------------------------------------------------------
+ifeq ($(strip $(CPPFILES)),)
+#---------------------------------------------------------------------------------
+ export LD := $(CC)
+#---------------------------------------------------------------------------------
+else
+#---------------------------------------------------------------------------------
+ export LD := $(CXX)
+#---------------------------------------------------------------------------------
+endif
+#---------------------------------------------------------------------------------
+
+export OFILES_BIN := $(addsuffix .o,$(BINFILES))
+export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
+export OFILES := $(OFILES_BIN) $(OFILES_SRC)
+export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
+
+export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
+ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
+ -I$(CURDIR)/$(BUILD)
+
+export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
+
+.PHONY: $(BUILD) clean all
+
+#---------------------------------------------------------------------------------
+all: $(BUILD)
+
+lib:
+ @[ -d $@ ] || mkdir -p $@
+
+$(BUILD) : lib
+ @[ -d $@ ] || mkdir -p $@
+ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.switch
+
+#---------------------------------------------------------------------------------
+clean:
+ @echo clean ...
+ @rm -rf build lib
+
+#---------------------------------------------------------------------------------
+else
+.PHONY: all
+
+DEPENDS := $(OFILES:.o=.d)
+
+#---------------------------------------------------------------------------------
+# main targets
+#---------------------------------------------------------------------------------
+
+$(OUTPUT) : $(OFILES)
+
+$(OFILES_SRC) : $(HFILES)
+$(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
+#---------------------------------------------------------------------------------------
\ No newline at end of file
diff --git a/ZAPDTR/ZAPDUtils/ZAPDUtils.vcxproj b/ZAPDTR/ZAPDUtils/ZAPDUtils.vcxproj
index 05b9e1908..164f4bb11 100644
--- a/ZAPDTR/ZAPDUtils/ZAPDUtils.vcxproj
+++ b/ZAPDTR/ZAPDUtils/ZAPDUtils.vcxproj
@@ -186,12 +186,6 @@
-
-
- {02d10590-9542-3f55-aaf8-6055677e2a2a}
- false
-
-
diff --git a/libultraship/Makefile b/libultraship/Makefile
index 18dfca271..37640969d 100644
--- a/libultraship/Makefile
+++ b/libultraship/Makefile
@@ -9,6 +9,7 @@ UNAME := $(shell uname)
ASAN ?= 0
DEBUG ?= 1
OPTFLAGS ?= -O0
+X11 ?= 0
LTO ?= 0
# flag to save whether the compiler being used is clang or gcc by checking CXX --version
@@ -49,6 +50,11 @@ CPPFLAGS := -MMD
MMFLAGS := -Wno-deprecated-declarations -ObjC++ -fobjc-weak -fobjc-arc
+ifeq ($(X11), 1)
+CXXFLAGS += -DX11_SUPPORTED
+CFLAGS += -DX11_SUPPORTED
+endif
+
# if not using clang, ask clang to use gcc standard library
ifneq ($(CXX_IS_CLANG),1)
STD_ISYSTEM=$(shell ${CXX} -xc++ -E -v - < /dev/null 2>&1 | grep "> search starts here" -A2 | tail -n 2 | head -n 1)
diff --git a/libultraship/Makefile.switch b/libultraship/Makefile.switch
new file mode 100644
index 000000000..72f0171aa
--- /dev/null
+++ b/libultraship/Makefile.switch
@@ -0,0 +1,192 @@
+#---------------------------------------------------------------------------------
+.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.
+#---------------------------------------------------------------------------------
+TARGET := ultraship
+BUILD := build
+SOURCES := \
+ libultraship/Factories \
+ libultraship/Lib/Fast3D \
+ libultraship/Lib/ImGui \
+ libultraship/Lib/Mercury \
+ libultraship
+DATA :=
+INCLUDES := \
+ ../ZAPDTR/ZAPDUtils \
+ ../StormLib/src \
+ libultraship/Lib/Fast3D/U64 \
+ libultraship/Lib/ImGui \
+ libultraship/Lib/spdlog \
+ libultraship/Lib/spdlog/include \
+ libultraship
+
+#-------------------------------------------------------------------------------
+# source files
+#-------------------------------------------------------------------------------
+
+SOURCEFILES_C := \
+ libultraship/mixer.c \
+ libultraship/Lib/stb/stb_impl.c \
+
+SOURCEFILES_CPP := \
+ libultraship/Lib/ImGui/backends/imgui_impl_opengl3.cpp \
+ libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp \
+ libultraship/Lib/StrHash64.cpp \
+ libultraship/Lib/tinyxml2/tinyxml2.cpp
+
+#---------------------------------------------------------------------------------
+# options for code generation
+#---------------------------------------------------------------------------------
+ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE -ffast-math -O3
+
+CFLAGS := -Wall -ffunction-sections \
+ $(ARCH) $(DEFINES) \
+ -DSPDLOG_NO_THREAD_ID \
+ -DSTBI_NO_THREAD_LOCALS
+
+CFLAGS += $(INCLUDE) -D__SWITCH__ -DENABLE_OPENGL
+
+CXXFLAGS := $(CFLAGS) -std=gnu++20
+CFLAGS += -std=gnu11
+
+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)/lib/lib$(TARGET).a
+export TOPDIR := $(CURDIR)
+
+export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
+ $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
+ $(foreach sf,$(SOURCEFILES_C),$(CURDIR)/$(dir $(sf))) \
+ $(foreach sf,$(SOURCEFILES_CPP),$(CURDIR)/$(dir $(sf)))
+
+export DEPSDIR := $(CURDIR)/$(BUILD)
+
+CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) \
+ $(foreach f,$(SOURCEFILES_C),$(notdir $(f)))
+CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) \
+ $(foreach f,$(SOURCEFILES_CPP),$(notdir $(f)))
+SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
+BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
+
+#---------------------------------------------------------------------------------
+# use CXX for linking C++ projects, CC for standard C
+#---------------------------------------------------------------------------------
+ifeq ($(strip $(CPPFILES)),)
+#---------------------------------------------------------------------------------
+ export LD := $(CC)
+#---------------------------------------------------------------------------------
+else
+#---------------------------------------------------------------------------------
+ export LD := $(CXX)
+#---------------------------------------------------------------------------------
+endif
+#---------------------------------------------------------------------------------
+
+export OFILES_BIN := $(addsuffix .o,$(BINFILES))
+export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
+export OFILES := $(OFILES_BIN) $(OFILES_SRC)
+export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
+
+export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
+ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
+ -I$(CURDIR)/$(BUILD)
+
+export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
+
+.PHONY: $(BUILD) clean all
+
+#---------------------------------------------------------------------------------
+all: $(BUILD)
+
+lib:
+ @[ -d $@ ] || mkdir -p $@
+
+$(BUILD) : lib
+ @[ -d $@ ] || mkdir -p $@
+ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.switch
+
+#---------------------------------------------------------------------------------
+clean:
+ @echo clean ...
+ @rm -rf build lib
+
+#---------------------------------------------------------------------------------
+else
+.PHONY: all
+
+DEPENDS := $(OFILES:.o=.d)
+
+#---------------------------------------------------------------------------------
+# main targets
+#---------------------------------------------------------------------------------
+
+$(OUTPUT) : $(OFILES)
+
+$(OFILES_SRC) : $(HFILES)
+$(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
+#---------------------------------------------------------------------------------------
\ No newline at end of file
diff --git a/libultraship/libultraship/Archive.cpp b/libultraship/libultraship/Archive.cpp
index c57fb608c..81b0e180e 100644
--- a/libultraship/libultraship/Archive.cpp
+++ b/libultraship/libultraship/Archive.cpp
@@ -6,6 +6,10 @@
#include "Lib/StrHash64.h"
#include
+#ifdef __SWITCH__
+#include "SwitchImpl.h"
+#endif
+
namespace Ship {
Archive::Archive(const std::string& MainPath, bool enableWriting) : Archive(MainPath, "", enableWriting)
{
@@ -68,7 +72,7 @@ namespace Ship {
//}
if (!attempt) {
- printf("({%i}) Failed to open file {%s} from mpq archive {%s}", GetLastError(), filePath.c_str(), MainPath.c_str());
+ SPDLOG_ERROR("({}) Failed to open file {} from mpq archive {}.", GetLastError(), filePath.c_str(), MainPath.c_str());
std::unique_lock Lock(FileToLoad->FileLoadMutex);
FileToLoad->bHasLoadError = true;
return FileToLoad;
@@ -327,13 +331,21 @@ namespace Ship {
#ifdef _WIN32
std::wstring wfullPath = std::filesystem::absolute(MainPath).wstring();
#endif
+#if defined(__SWITCH__)
+ std::string fullPath = MainPath;
+#else
std::string fullPath = std::filesystem::absolute(MainPath).string();
+#endif
#ifdef _WIN32
if (!SFileOpenArchive(wfullPath.c_str(), 0, enableWriting ? 0 : MPQ_OPEN_READ_ONLY, &mpqHandle)) {
#else
if (!SFileOpenArchive(fullPath.c_str(), 0, enableWriting ? 0 : MPQ_OPEN_READ_ONLY, &mpqHandle)) {
#endif
+
+ #ifdef __SWITCH__
+ Switch::ThrowMissingOTR(fullPath);
+ #endif
SPDLOG_ERROR("({}) Failed to open main mpq file {}.", GetLastError(), fullPath.c_str());
return false;
}
@@ -362,7 +374,11 @@ namespace Ship {
bool Archive::LoadPatchMPQ(const std::string& path) {
HANDLE patchHandle = NULL;
+#if defined(__SWITCH__)
+ std::string fullPath = path;
+#else
std::string fullPath = std::filesystem::absolute(path).string();
+#endif
if (mpqHandles.contains(fullPath)) {
return true;
}
diff --git a/libultraship/libultraship/Console.cpp b/libultraship/libultraship/Console.cpp
index da61e4056..85ba1f78d 100644
--- a/libultraship/libultraship/Console.cpp
+++ b/libultraship/libultraship/Console.cpp
@@ -98,20 +98,14 @@ void Console::Update() {
}
}
-extern "C" uint8_t __enableGameInput;
-
void Console::Draw() {
bool input_focus = false;
- __enableGameInput = true;
if (!this->opened) return;
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
ImGui::Begin("Console", nullptr, ImGuiWindowFlags_NoFocusOnAppearing);
const ImVec2 pos = ImGui::GetWindowPos();
const ImVec2 size = ImGui::GetWindowSize();
-
- __enableGameInput = !ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows);
-
// SohImGui::ShowCursor(ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows | ImGuiHoveredFlags_RectOnly), SohImGui::Dialogues::dConsole);
// Renders autocomplete window
@@ -230,8 +224,8 @@ void Console::Draw() {
// Renders input textfield
constexpr ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackEdit |
ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
- ImGui::PushItemWidth(-1);
- if(ImGui::InputTextWithHint("CMDInput", ">", this->InputBuffer, MAX_BUFFER_SIZE, flags, &Console::CallbackStub, this)) {
+ ImGui::PushItemWidth(-53);
+ if(ImGui::InputTextWithHint("##CMDInput", ">", this->InputBuffer, MAX_BUFFER_SIZE, flags, &Console::CallbackStub, this)) {
input_focus = true;
if(this->InputBuffer[0] != '\0' && this->InputBuffer[0] != ' ')
this->Dispatch(std::string(this->InputBuffer));
@@ -250,6 +244,13 @@ void Console::Draw() {
}
}
+ ImGui::SameLine();
+ ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 50);
+ if(ImGui::Button("Submit") && !input_focus && this->InputBuffer[0] != '\0' && this->InputBuffer[0] != ' '){
+ this->Dispatch(std::string(this->InputBuffer));
+ memset(this->InputBuffer, 0, MAX_BUFFER_SIZE);
+ }
+
ImGui::SetItemDefaultFocus();
if (input_focus) ImGui::SetKeyboardFocusHere(-1);
ImGui::PopItemWidth();
diff --git a/libultraship/libultraship/Cvar.cpp b/libultraship/libultraship/Cvar.cpp
index 231308fe7..27d44df80 100644
--- a/libultraship/libultraship/Cvar.cpp
+++ b/libultraship/libultraship/Cvar.cpp
@@ -14,7 +14,7 @@ extern "C" CVar* CVar_Get(const char* name) {
return (it != cvars.end()) ? it->second.get() : nullptr;
}
-extern "C" s32 CVar_GetS32(const char* name, s32 defaultValue) {
+extern "C" int32_t CVar_GetS32(const char* name, int32_t defaultValue) {
CVar* cvar = CVar_Get(name);
if (cvar) {
@@ -47,7 +47,7 @@ extern "C" const char* CVar_GetString(const char* name, const char* defaultValue
return defaultValue;
}
-extern "C" void CVar_SetS32(const char* name, s32 value) {
+extern "C" void CVar_SetS32(const char* name, int32_t value) {
auto& cvar = cvars[name];
if (!cvar) {
cvar = std::make_unique();
@@ -74,7 +74,7 @@ extern "C" void CVar_SetString(const char* name, const char* value) {
cvar->value.valueStr = ImStrdup(value);
}
-extern "C" void CVar_RegisterS32(const char* name, s32 defaultValue) {
+extern "C" void CVar_RegisterS32(const char* name, int32_t defaultValue) {
if (!CVar_Get(name))
CVar_SetS32(name, defaultValue);
}
diff --git a/libultraship/libultraship/Cvar.h b/libultraship/libultraship/Cvar.h
index f9583ef0c..1507b519d 100644
--- a/libultraship/libultraship/Cvar.h
+++ b/libultraship/libultraship/Cvar.h
@@ -1,7 +1,7 @@
#ifndef _CVAR_H
#define _CVAR_H
-#include
+#include
typedef enum CVarType { CVAR_TYPE_S32, CVAR_TYPE_FLOAT, CVAR_TYPE_STRING } CVarType;
@@ -10,7 +10,7 @@ typedef struct CVar {
CVarType type;
union {
- s32 valueS32;
+ int32_t valueS32;
float valueFloat;
const char* valueStr;
} value;
@@ -23,13 +23,13 @@ extern "C"
//#include
CVar* CVar_Get(const char* name);
-s32 CVar_GetS32(const char* name, s32 defaultValue);
+int32_t CVar_GetS32(const char* name, int32_t defaultValue);
float CVar_GetFloat(const char* name, float defaultValue);
const char* CVar_GetString(const char* name, const char* defaultValue);
-void CVar_SetS32(const char* name, s32 value);
+void CVar_SetS32(const char* name, int32_t value);
void CVar_SetString(const char* name, const char* value);
-void CVar_RegisterS32(const char* name, s32 defaultValue);
+void CVar_RegisterS32(const char* name, int32_t defaultValue);
void CVar_RegisterFloat(const char* name, float defaultValue);
void CVar_RegisterString(const char* name, const char* defaultValue);
diff --git a/libultraship/libultraship/Environment.cpp b/libultraship/libultraship/Environment.cpp
index 7f10c8c44..53d0f330b 100644
--- a/libultraship/libultraship/Environment.cpp
+++ b/libultraship/libultraship/Environment.cpp
@@ -9,6 +9,7 @@ namespace SohUtils {
void saveEnvironmentVar(const std::string& key, const std::string& value) {
environmentVars[key] = value;
}
+
std::string getEnvironmentVar(const std::string& key) {
return environmentVars[key];
}
diff --git a/libultraship/libultraship/GameOverlay.h b/libultraship/libultraship/GameOverlay.h
index 605cd5898..c9290390e 100644
--- a/libultraship/libultraship/GameOverlay.h
+++ b/libultraship/libultraship/GameOverlay.h
@@ -38,5 +38,5 @@ namespace Ship {
void LoadFont(const std::string& name, const std::string& path, float fontSize);
};
- static bool OverlayCommand(const std::vector& args);
+ bool OverlayCommand(const std::vector& args);
}
diff --git a/libultraship/libultraship/GlobalCtx2.cpp b/libultraship/libultraship/GlobalCtx2.cpp
index 329644192..5eb449ad3 100644
--- a/libultraship/libultraship/GlobalCtx2.cpp
+++ b/libultraship/libultraship/GlobalCtx2.cpp
@@ -10,6 +10,8 @@
#include "ModManager.h"
#ifdef __APPLE__
#include "OSXFolderManager.h"
+#elif defined(__SWITCH__)
+#include "SwitchImpl.h"
#endif
namespace Ship {
@@ -72,11 +74,16 @@ namespace Ship {
{
#ifdef _WIN32
MessageBox(nullptr, L"Main OTR file not found!", L"Uh oh", MB_OK);
+#elif defined(__SWITCH__)
+ printf("Main OTR file not found!\n");
#else
SPDLOG_ERROR("Main OTR file not found!");
#endif
exit(1);
}
+ #ifdef __SWITCH__
+ Ship::Switch::Init(PostInitPhase);
+ #endif
INSTANCE = new ModManager(ResMan);
INSTANCE->Init();
}
diff --git a/libultraship/libultraship/ImGuiImpl.cpp b/libultraship/libultraship/ImGuiImpl.cpp
index f1f1fd12b..f7288ae3a 100644
--- a/libultraship/libultraship/ImGuiImpl.cpp
+++ b/libultraship/libultraship/ImGuiImpl.cpp
@@ -27,6 +27,16 @@
#include "Lib/spdlog/include/spdlog/common.h"
#include "Utils/StringHelper.h"
+#if __APPLE__
+#include
+#else
+#include
+#endif
+
+#ifdef __SWITCH__
+#include "SwitchImpl.h"
+#endif
+
#ifdef ENABLE_OPENGL
#include "Lib/ImGui/backends/imgui_impl_opengl3.h"
#include "Lib/ImGui/backends/imgui_impl_sdl.h"
@@ -127,6 +137,7 @@ namespace SohImGui {
void ImGuiWMInit() {
switch (impl.backend) {
case Backend::SDL:
+ SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "1");
ImGui_ImplSDL2_InitForOpenGL(static_cast(impl.sdl.window), impl.sdl.context);
break;
#if defined(ENABLE_DX11) || defined(ENABLE_DX12)
@@ -339,10 +350,17 @@ namespace SohImGui {
io = &ImGui::GetIO();
io->ConfigFlags |= ImGuiConfigFlags_DockingEnable;
io->Fonts->AddFontDefault();
+ #ifdef __SWITCH__
+ Ship::Switch::SetupFont(io->Fonts);
+ #endif
lastBackendID = GetBackendID(GlobalCtx2::GetInstance()->GetConfig());
if (CVar_GetS32("gOpenMenuBar", 0) != 1) {
+ #ifdef __SWITCH__
+ SohImGui::overlay->TextDrawNotification(30.0f, true, "Press - to access enhancements menu");
+ #else
SohImGui::overlay->TextDrawNotification(30.0f, true, "Press F1 to access enhancements menu");
+ #endif
}
auto imguiIniPath = Ship::GlobalCtx2::GetPathRelativeToAppDirectory("imgui.ini");
@@ -358,6 +376,9 @@ namespace SohImGui {
controller->Init();
ImGuiWMInit();
ImGuiBackendInit();
+ #ifdef __SWITCH__
+ ImGui::GetStyle().ScaleAllSizes(2);
+ #endif
ModInternal::RegisterHook([] {
if (GlobalCtx2::GetInstance()->GetWindow()->IsFullscreen())
@@ -386,7 +407,10 @@ namespace SohImGui {
CVar_SetS32("gNewSeedGenerated", 0);
CVar_SetS32("gNewFileDropped", 0);
CVar_SetString("gDroppedFile", "None");
- // Game::SaveSettings();
+
+ #ifdef __SWITCH__
+ Switch::ApplyOverclock();
+ #endif
}
void Update(EventImpl event) {
@@ -734,7 +758,7 @@ namespace SohImGui {
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos);
- ImGui::SetNextWindowSize(ImVec2(wnd->GetCurrentWidth(), wnd->GetCurrentHeight()));
+ ImGui::SetNextWindowSize(ImVec2((int) wnd->GetCurrentWidth(), (int) wnd->GetCurrentHeight()));
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
@@ -757,7 +781,7 @@ namespace SohImGui {
ImGui::DockSpace(dockId, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_None | ImGuiDockNodeFlags_NoDockingInCentralNode);
- if (ImGui::IsKeyPressed(TOGGLE_BTN)) {
+ if (ImGui::IsKeyPressed(TOGGLE_BTN) || ImGui::IsKeyPressed(TOGGLE_PAD_BTN)) {
bool menu_bar = CVar_GetS32("gOpenMenuBar", 0);
CVar_SetS32("gOpenMenuBar", !menu_bar);
needs_save = true;
@@ -791,8 +815,13 @@ namespace SohImGui {
if (ImGui::BeginMenuBar()) {
if (DefaultAssets.contains("Game_Icon")) {
+ #ifdef __SWITCH__
+ ImVec2 iconSize = ImVec2(20.0f, 20.0f);
+ #else
+ ImVec2 iconSize = ImVec2(16.0f, 16.0f);
+ #endif
ImGui::SetCursorPos(ImVec2(5, 2.5f));
- ImGui::Image(GetTextureByID(DefaultAssets["Game_Icon"]->textureId), ImVec2(16.0f, 16.0f));
+ ImGui::Image(GetTextureByID(DefaultAssets["Game_Icon"]->textureId), iconSize);
ImGui::SameLine();
ImGui::SetCursorPos(ImVec2(25, 0));
}
@@ -931,8 +960,6 @@ namespace SohImGui {
EXPERIMENTAL();
ImGui::Text("Texture Filter (Needs reload)");
EnhancementCombobox("gTextureFilter", filters, 3, 0);
- GfxRenderingAPI* gapi = gfx_get_current_rendering_api();
- gapi->set_texture_filter((FilteringMode)CVar_GetS32("gTextureFilter", 0));
overlay->DrawSettings();
ImGui::EndMenu();
}
@@ -1235,8 +1262,16 @@ namespace SohImGui {
const char* fps_cvar = "gInterpolationFPS";
{
- int val = CVar_GetS32(fps_cvar, 20);
- val = MAX(MIN(val, 250), 20);
+ #ifdef __SWITCH__
+ int minFps = 20;
+ int maxFps = 60;
+ #else
+ int minFps = 20;
+ int maxFps = 250;
+ #endif
+
+ int val = CVar_GetS32(fps_cvar, minFps);
+ val = MAX(MIN(val, maxFps), 20);
int fps = val;
if (fps == 20)
@@ -1258,7 +1293,7 @@ namespace SohImGui {
ImGui::SameLine();
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
- if (ImGui::SliderInt("##FPSInterpolation", &val, 20, 250, "", ImGuiSliderFlags_AlwaysClamp))
+ if (ImGui::SliderInt("##FPSInterpolation", &val, minFps, maxFps, "", ImGuiSliderFlags_AlwaysClamp))
{
if (val > 250)
{
@@ -1316,6 +1351,23 @@ namespace SohImGui {
EnhancementCheckbox("Free Camera", "gFreeCamera");
Tooltip("Enables camera control\nNote: You must remap C buttons off of\nthe right stick in the controller\nconfig menu, and map the camera stick\nto the right stick.");
+ #ifdef __SWITCH__
+ int slot = CVar_GetS32("gSwitchPerfMode", (int)SwitchProfiles::STOCK);
+ ImGui::Text("Switch performance mode");
+ if (ImGui::BeginCombo("##perf", SWITCH_CPU_PROFILES[slot])) {
+ for (int sId = 0; sId <= SwitchProfiles::POWERSAVINGM3; sId++) {
+ if (ImGui::Selectable(SWITCH_CPU_PROFILES[sId], sId == slot)) {
+ INFO("Profile:: %s", SWITCH_CPU_PROFILES[sId]);
+ CVar_SetS32("gSwitchPerfMode", sId);
+ Switch::ApplyOverclock();
+ needs_save = true;
+ }
+
+ }
+ ImGui::EndCombo();
+ }
+ #endif
+
ImGui::EndMenu();
}
@@ -1430,6 +1482,8 @@ namespace SohImGui {
ImGui::Text("Platform: Windows");
#elif __APPLE__
ImGui::Text("Platform: macOS");
+#elif defined(__SWITCH__)
+ ImGui::Text("Platform: Nintendo Switch");
#else
ImGui::Text("Platform: Linux");
#endif
diff --git a/libultraship/libultraship/InputEditor.cpp b/libultraship/libultraship/InputEditor.cpp
index 25e641a06..eb191cc20 100644
--- a/libultraship/libultraship/InputEditor.cpp
+++ b/libultraship/libultraship/InputEditor.cpp
@@ -9,7 +9,6 @@
namespace Ship {
- extern "C" uint8_t __enableGameInput;
#define SEPARATION() ImGui::Dummy(ImVec2(0, 5))
void InputEditor::Init() {
@@ -116,7 +115,11 @@ namespace Ship {
DrawButton("Z", BTN_Z);
DrawButton("START", BTN_START);
SEPARATION();
+ #ifdef __SWITCH__
+ SohImGui::EndGroupPanel(IsKeyboard ? 7.0f : 56.0f);
+ #else
SohImGui::EndGroupPanel(IsKeyboard ? 7.0f : 48.0f);
+ #endif
ImGui::SameLine();
SohImGui::BeginGroupPanel("Digital Pad", ImVec2(150, 20));
DrawButton("Up", BTN_DUP);
@@ -124,7 +127,11 @@ namespace Ship {
DrawButton("Left", BTN_DLEFT);
DrawButton("Right", BTN_DRIGHT);
SEPARATION();
+ #ifdef __SWITCH__
+ SohImGui::EndGroupPanel(IsKeyboard ? 53.0f : 122.0f);
+ #else
SohImGui::EndGroupPanel(IsKeyboard ? 53.0f : 94.0f);
+ #endif
ImGui::SameLine();
SohImGui::BeginGroupPanel("Analog Stick", ImVec2(150, 20));
DrawButton("Up", BTN_STICKUP);
@@ -148,7 +155,11 @@ namespace Ship {
} else {
ImGui::Dummy(ImVec2(0, 6));
}
- SohImGui::EndGroupPanel(IsKeyboard ? 52.0f : 24.0f);
+ #ifdef __SWITCH__
+ SohImGui::EndGroupPanel(IsKeyboard ? 52.0f : 52.0f);
+ #else
+ SohImGui::EndGroupPanel(IsKeyboard ? 52.0f : 24.0f);
+ #endif
ImGui::SameLine();
if (!IsKeyboard) {
@@ -174,44 +185,52 @@ namespace Ship {
ImGui::InputFloat("##MSensitivity", &profile.Thresholds[SENSITIVITY], 1.0f, 0.0f, "%.0f");
ImGui::PopItemWidth();
ImGui::EndChild();
+ #ifdef __SWITCH__
+ SohImGui::EndGroupPanel(43.0f);
+ #else
SohImGui::EndGroupPanel(14.0f);
+ #endif
}
if(Backend->CanGyro()) {
ImGui::SameLine();
SohImGui::BeginGroupPanel("Gyro Options", ImVec2(175, 20));
- float cursorX = ImGui::GetCursorPosX() + 5;
- ImGui::SetCursorPosX(cursorX);
- ImGui::Checkbox("Enable Gyro", &profile.UseGyro);
- ImGui::SetCursorPosX(cursorX);
- ImGui::Text("Gyro Sensitivity: %d%%", static_cast(100.0f * profile.Thresholds[GYRO_SENSITIVITY]));
- ImGui::PushItemWidth(135.0f);
- ImGui::SetCursorPosX(cursorX);
- ImGui::SliderFloat("##GSensitivity", &profile.Thresholds[GYRO_SENSITIVITY], 0.0f, 1.0f, "");
- ImGui::PopItemWidth();
- ImGui::Dummy(ImVec2(0, 1));
- ImGui::SetCursorPosX(cursorX);
- if (ImGui::Button("Recalibrate Gyro##RGyro")) {
- profile.Thresholds[DRIFT_X] = 0.0f;
- profile.Thresholds[DRIFT_Y] = 0.0f;
- }
- ImGui::SetCursorPosX(cursorX);
- DrawVirtualStick("##GyroPreview", ImVec2(-10.0f * Backend->wGyroY, 10.0f * Backend->wGyroX));
+ float cursorX = ImGui::GetCursorPosX() + 5;
+ ImGui::SetCursorPosX(cursorX);
+ ImGui::Checkbox("Enable Gyro", &profile.UseGyro);
+ ImGui::SetCursorPosX(cursorX);
+ ImGui::Text("Gyro Sensitivity: %d%%", static_cast(100.0f * profile.Thresholds[GYRO_SENSITIVITY]));
+ ImGui::PushItemWidth(135.0f);
+ ImGui::SetCursorPosX(cursorX);
+ ImGui::SliderFloat("##GSensitivity", &profile.Thresholds[GYRO_SENSITIVITY], 0.0f, 1.0f, "");
+ ImGui::PopItemWidth();
+ ImGui::Dummy(ImVec2(0, 1));
+ ImGui::SetCursorPosX(cursorX);
+ if (ImGui::Button("Recalibrate Gyro##RGyro")) {
+ profile.Thresholds[DRIFT_X] = 0.0f;
+ profile.Thresholds[DRIFT_Y] = 0.0f;
+ }
+ ImGui::SetCursorPosX(cursorX);
+ DrawVirtualStick("##GyroPreview", ImVec2(-10.0f * Backend->wGyroY, 10.0f * Backend->wGyroX));
- ImGui::SameLine();
- ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
- ImGui::BeginChild("##GyInput", ImVec2(90, 85), false);
- ImGui::Text("Drift X");
- ImGui::PushItemWidth(80);
- ImGui::InputFloat("##GDriftX", &profile.Thresholds[DRIFT_X], 1.0f, 0.0f, "%.1f");
- ImGui::PopItemWidth();
- ImGui::Text("Drift Y");
- ImGui::PushItemWidth(80);
- ImGui::InputFloat("##GDriftY", &profile.Thresholds[DRIFT_Y], 1.0f, 0.0f, "%.1f");
- ImGui::PopItemWidth();
- ImGui::EndChild();
+ ImGui::SameLine();
+ ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
+ ImGui::BeginChild("##GyInput", ImVec2(90, 85), false);
+ ImGui::Text("Drift X");
+ ImGui::PushItemWidth(80);
+ ImGui::InputFloat("##GDriftX", &profile.Thresholds[DRIFT_X], 1.0f, 0.0f, "%.1f");
+ ImGui::PopItemWidth();
+ ImGui::Text("Drift Y");
+ ImGui::PushItemWidth(80);
+ ImGui::InputFloat("##GDriftY", &profile.Thresholds[DRIFT_Y], 1.0f, 0.0f, "%.1f");
+ ImGui::PopItemWidth();
+ ImGui::EndChild();
+ #ifdef __SWITCH__
+ SohImGui::EndGroupPanel(46.0f);
+ #else
SohImGui::EndGroupPanel(14.0f);
+ #endif
}
ImGui::SameLine();
@@ -227,7 +246,11 @@ namespace Ship {
SohImGui::EndGroupPanel();
ImGui::SetCursorPosX(cursor.x);
+ #ifdef __SWITCH__
+ ImGui::SetCursorPosY(cursor.y + 167);
+ #else
ImGui::SetCursorPosY(cursor.y + 120);
+ #endif
SohImGui::BeginGroupPanel("Options", ImVec2(158, 20));
float cursorX = ImGui::GetCursorPosX() + 5;
ImGui::SetCursorPosX(cursorX);
@@ -245,16 +268,21 @@ namespace Ship {
}
void InputEditor::DrawHud() {
-
- __enableGameInput = true;
-
if (!this->Opened) {
BtnReading = -1;
CVar_SetS32("gControllerConfigurationEnabled", 0);
return;
}
- ImGui::SetNextWindowSizeConstraints(ImVec2(641, 250), ImVec2(1200, 290));
+#ifdef __SWITCH__
+ ImVec2 minSize = ImVec2(641, 250);
+ ImVec2 maxSize = ImVec2(2200, 505);
+#else
+ ImVec2 minSize = ImVec2(641, 250);
+ ImVec2 maxSize = ImVec2(1200, 290);
+#endif
+
+ ImGui::SetNextWindowSizeConstraints(minSize, maxSize);
//OTRTODO: Disable this stupid workaround ( ReadRawPress() only works when the window is on the main viewport )
ImGui::SetNextWindowViewport(ImGui::GetMainViewport()->ID);
ImGui::Begin("Controller Configuration", &this->Opened, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize);
diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_glx.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_glx.cpp
index 43dae33ff..0576583d8 100644
--- a/libultraship/libultraship/Lib/Fast3D/gfx_glx.cpp
+++ b/libultraship/libultraship/Lib/Fast3D/gfx_glx.cpp
@@ -1,4 +1,4 @@
-#ifdef __linux__
+#if defined(__linux__) && defined(X11_SUPPORTED)
#include
#include
#include
@@ -156,6 +156,7 @@ static struct {
Atom atom_wm_delete_window;
bool is_fullscreen;
+ bool is_running = true;
void (*on_fullscreen_changed)(bool is_now_fullscreen);
int keymap[256];
@@ -399,7 +400,7 @@ static void gfx_glx_set_keyboard_callbacks(bool (*on_key_down)(int scancode), bo
}
static void gfx_glx_main_loop(void (*run_one_game_iter)(void)) {
- while (1) {
+ while (glx.is_running) {
run_one_game_iter();
}
}
@@ -440,7 +441,7 @@ static void gfx_glx_handle_events(void) {
}
}
if (xev.type == ClientMessage && (Atom)xev.xclient.data.l[0] == glx.atom_wm_delete_window) {
- exit(0);
+ glx.is_running = false;
}
}
}
diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp
index d79c3aa8f..ad683e047 100644
--- a/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp
+++ b/libultraship/libultraship/Lib/Fast3D/gfx_opengl.cpp
@@ -31,6 +31,9 @@
#elif __APPLE__
#include
#include
+#elif __SWITCH__
+#include
+#include
#else
#include
#include
@@ -643,6 +646,10 @@ static void gfx_opengl_upload_texture(const uint8_t *rgba32_buf, uint32_t width,
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgba32_buf);
}
+#ifdef __SWITCH__
+#define GL_MIRROR_CLAMP_TO_EDGE 0x8743
+#endif
+
static uint32_t gfx_cm_to_opengl(uint32_t val) {
switch (val) {
case G_TX_NOMIRROR | G_TX_CLAMP:
@@ -710,9 +717,9 @@ static void gfx_opengl_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_
}
static void gfx_opengl_init(void) {
-//#if FOR_WINDOWS
+#ifndef __SWITCH__
glewInit();
-//#endif
+#endif
glGenBuffers(1, &opengl_vbo);
glBindBuffer(GL_ARRAY_BUFFER, opengl_vbo);
@@ -840,9 +847,7 @@ void gfx_opengl_start_draw_to_framebuffer(int fb_id, float noise_scale) {
if (noise_scale != 0.0f) {
current_noise_scale = 1.0f / noise_scale;
}
-
glBindFramebuffer(GL_FRAMEBUFFER, fb.fbo);
-
current_framebuffer = fb_id;
}
diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp
index 0a04c9580..dd5f9bf95 100644
--- a/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp
+++ b/libultraship/libultraship/Lib/Fast3D/gfx_pc.cpp
@@ -1206,8 +1206,8 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo
rdp.viewport_or_scissor_changed = false;
}
- uint64_t cc_id = rdp.combine_mode;
+ uint64_t cc_id = rdp.combine_mode;
bool use_alpha = (rdp.other_mode_l & (3 << 20)) == (G_BL_CLR_MEM << 20) && (rdp.other_mode_l & (3 << 16)) == (G_BL_1MA << 16);
bool use_fog = (rdp.other_mode_l >> 30) == G_BL_CLR_FOG;
bool texture_edge = (rdp.other_mode_l & CVG_X_ALPHA) == CVG_X_ALPHA;
diff --git a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp
index cb0d7a7f0..2576bc17b 100644
--- a/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp
+++ b/libultraship/libultraship/Lib/Fast3D/gfx_sdl2.cpp
@@ -15,6 +15,11 @@
#include "SDL_opengl.h"
#elif __APPLE__
#include
+#elif __SWITCH__
+#include
+#include
+#include
+#include "../../SwitchImpl.h"
#else
#include
#define GL_GLEXT_PROTOTYPES 1
@@ -42,6 +47,7 @@ static int vsync_enabled = 0;
static int window_width = DESIRED_SCREEN_WIDTH;
static int window_height = DESIRED_SCREEN_HEIGHT;
static bool fullscreen_state;
+static bool is_running = true;
static void (*on_fullscreen_changed_callback)(bool is_now_fullscreen);
static bool (*on_key_down_callback)(int scancode);
static bool (*on_key_up_callback)(int scancode);
@@ -146,31 +152,43 @@ static void gfx_sdl_init(const char *game_name, bool start_in_fullscreen, uint32
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+#elif defined(__SWITCH__)
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
#endif
#ifdef _WIN32
timer = CreateWaitableTimer(nullptr, false, nullptr);
#endif
- //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
- //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
-
char title[512];
int len = sprintf(title, "%s (%s)", game_name, GFX_API_NAME);
- window_width = width;
- window_height = height;
+#ifdef __SWITCH__
+ // For Switch we need to set the window width before creating the window
+ Ship::Switch::GetDisplaySize(&window_width, &window_height);
+#endif
wnd = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
window_width, window_height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
+
+#ifndef __SWITCH__
SDL_GL_GetDrawableSize(wnd, &window_width, &window_height);
if (start_in_fullscreen) {
set_fullscreen(true, false);
}
+#endif
ctx = SDL_GL_CreateContext(wnd);
+#ifdef __SWITCH__
+ if(!gladLoadGLLoader(SDL_GL_GetProcAddress)){
+ printf("Failed to initialize glad\n");
+ }
+#endif
+
SDL_GL_SetSwapInterval(1);
SohImGui::WindowImpl window_impl;
@@ -211,14 +229,21 @@ static void gfx_sdl_set_keyboard_callbacks(bool (*on_key_down)(int scancode), bo
}
static void gfx_sdl_main_loop(void (*run_one_game_iter)(void)) {
- while (1)
- {
+#ifdef __SWITCH__
+ while(Ship::Switch::IsRunning()) {
+#else
+ while(is_running) {
+#endif
run_one_game_iter();
}
+#ifdef __SWITCH__
+ Ship::Switch::Exit();
+#endif
+ ModInternal::ExecuteHooks();
}
static void gfx_sdl_get_dimensions(uint32_t *width, uint32_t *height) {
- *width = window_width;
+ *width = window_width;
*height = window_height;
}
@@ -271,7 +296,11 @@ static void gfx_sdl_handle_events(void) {
#endif
case SDL_WINDOWEVENT:
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
- SDL_GL_GetDrawableSize(wnd, &window_width, &window_height);
+ #ifdef __SWITCH__
+ Ship::Switch::GetDisplaySize(&window_width, &window_height);
+ #else
+ SDL_GL_GetDrawableSize(wnd, &window_width, &window_height);
+ #endif
}
break;
case SDL_DROPFILE:
@@ -303,7 +332,7 @@ static inline void sync_framerate_with_timer(void) {
const int64_t next = previous_time + 10 * FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR;
const int64_t left = next - t;
if (left > 0) {
-#if defined __linux__ || defined __APPLE__
+#ifndef _WIN32
const timespec spec = { 0, left * 100 };
nanosleep(&spec, nullptr);
#else
diff --git a/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_opengl3.cpp b/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_opengl3.cpp
index b7587d0e7..6d4483a91 100644
--- a/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_opengl3.cpp
+++ b/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_opengl3.cpp
@@ -132,6 +132,10 @@
#else
#include // Use GL ES 3
#endif
+#elif defined(__SWITCH__)
+#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM
+#define GL_GLEXT_PROTOTYPES 1
+#include
#elif !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)
// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
// Helper libraries are often used for this purpose! Here we are using our own minimal custom loader based on gl3w.
diff --git a/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp b/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp
index 931660a9d..8cbdceac5 100644
--- a/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp
+++ b/libultraship/libultraship/Lib/ImGui/backends/imgui_impl_sdl.cpp
@@ -65,6 +65,7 @@
#include "imgui.h"
#include "imgui_impl_sdl.h"
+#include "imgui_internal.h"
// SDL
// (the multi-viewports feature requires SDL features supported from SDL 2.0.4+. SDL 2.0.5+ is highly recommended)
@@ -77,7 +78,7 @@
#include
#endif
-#if SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) && !defined(__amigaos4__)
+#if SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) && !defined(__amigaos4__) && !defined(__SWITCH__)
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 1
#else
#define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE 0
@@ -105,6 +106,7 @@ struct ImGui_ImplSDL2_Data
char* ClipboardTextData;
bool MouseCanUseGlobalState;
bool UseVulkan;
+ bool ShowingVirtualKeyboard;
ImGui_ImplSDL2_Data() { memset((void*)this, 0, sizeof(*this)); }
};
@@ -269,6 +271,23 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event)
{
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData();
+ ImGuiInputTextState* state = ImGui::GetInputTextState(ImGui::GetActiveID());
+
+ #ifdef __SWITCH__
+ if (io.WantTextInput) {
+ if (!bd->ShowingVirtualKeyboard) {
+ state->ClearText();
+
+ bd->ShowingVirtualKeyboard = true;
+ SDL_StartTextInput();
+ }
+ } else {
+ if (bd->ShowingVirtualKeyboard) {
+ bd->ShowingVirtualKeyboard = false;
+ SDL_StopTextInput();
+ }
+ }
+ #endif
switch (event->type)
{
@@ -411,6 +430,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
// Our mouse update function expect PlatformHandle to be filled for the main viewport
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
main_viewport->PlatformHandle = (void*)window;
+#if defined(_WIN32) || defined(__APPLE__)
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWindowWMInfo(window, &info))
@@ -421,6 +441,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void
main_viewport->PlatformHandleRaw = (void*)info.info.cocoa.window;
#endif
}
+#endif
// Set SDL hint to receive mouse click events on window focus, otherwise SDL doesn't emit the event.
// Without this, when clicking to gain focus, our widgets wouldn't activate even though they showed as hovered.
@@ -583,8 +604,11 @@ static void ImGui_ImplSDL2_UpdateMouseCursor()
static void ImGui_ImplSDL2_UpdateGamepads()
{
ImGuiIO& io = ImGui::GetIO();
- if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
- return;
+
+ // Remove this check because we always want to be able to trigger the menu via controller
+ // The ImGuiConfigFlags_NavEnableGamepad is still separately used by ImGui for enabling imgui navigation
+ // if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
+ // return;
// Get gamepad
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
@@ -600,10 +624,17 @@ static void ImGui_ImplSDL2_UpdateGamepads()
const int thumb_dead_zone = 8000; // SDL_gamecontroller.h suggests using this value.
MAP_BUTTON(ImGuiKey_GamepadStart, SDL_CONTROLLER_BUTTON_START);
MAP_BUTTON(ImGuiKey_GamepadBack, SDL_CONTROLLER_BUTTON_BACK);
+#ifdef __SWITCH__
+ MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_B); // Xbox A, PS Cross
+ MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_A); // Xbox B, PS Circle
+ MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_Y); // Xbox X, PS Square
+ MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_X); // Xbox Y, PS Triangle
+#else
MAP_BUTTON(ImGuiKey_GamepadFaceDown, SDL_CONTROLLER_BUTTON_A); // Xbox A, PS Cross
MAP_BUTTON(ImGuiKey_GamepadFaceRight, SDL_CONTROLLER_BUTTON_B); // Xbox B, PS Circle
MAP_BUTTON(ImGuiKey_GamepadFaceLeft, SDL_CONTROLLER_BUTTON_X); // Xbox X, PS Square
MAP_BUTTON(ImGuiKey_GamepadFaceUp, SDL_CONTROLLER_BUTTON_Y); // Xbox Y, PS Triangle
+#endif
MAP_BUTTON(ImGuiKey_GamepadDpadLeft, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
MAP_BUTTON(ImGuiKey_GamepadDpadRight, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
MAP_BUTTON(ImGuiKey_GamepadDpadUp, SDL_CONTROLLER_BUTTON_DPAD_UP);
@@ -757,6 +788,7 @@ static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport)
SDL_GL_MakeCurrent(vd->Window, backup_context);
viewport->PlatformHandle = (void*)vd->Window;
+#if defined(_WIN32) || defined(__APPLE__)
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (SDL_GetWindowWMInfo(vd->Window, &info))
@@ -767,6 +799,7 @@ static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport)
viewport->PlatformHandleRaw = (void*)info.info.cocoa.window;
#endif
}
+#endif
}
static void ImGui_ImplSDL2_DestroyWindow(ImGuiViewport* viewport)
diff --git a/libultraship/libultraship/SDLController.cpp b/libultraship/libultraship/SDLController.cpp
index 3d02a8614..398ce1944 100644
--- a/libultraship/libultraship/SDLController.cpp
+++ b/libultraship/libultraship/SDLController.cpp
@@ -4,6 +4,10 @@
#include "Window.h"
#include
+#ifdef _MSC_VER
+#define strdup _strdup
+#endif
+
extern "C" uint8_t __osMaxControllers;
namespace Ship {
@@ -25,11 +29,16 @@ namespace Ship {
char GuidBuf[33];
SDL_JoystickGetGUIDString(SDL_JoystickGetDeviceGUID(physicalSlot), GuidBuf, sizeof(GuidBuf));
- GUID = std::string(GuidBuf);
Cont = NewCont;
wCamX = 0;
wCamY = 0;
-
+#ifdef __SWITCH__
+ GUID = StringHelper::Sprintf("%s:%d", GuidBuf, physicalSlot);
+ ControllerName = StringHelper::Sprintf("%s #%d", SDL_GameControllerNameForIndex(physicalSlot), physicalSlot + 1);
+#else
+ GUID = std::string(GuidBuf);
+ ControllerName = std::string(SDL_GameControllerNameForIndex(physicalSlot));
+#endif
return true;
}
@@ -441,7 +450,7 @@ namespace Ship {
}
const char* SDLController::GetControllerName() {
- return SDL_GameControllerNameForIndex(physicalSlot);
+ return strdup(ControllerName.c_str());
}
void SDLController::CreateDefaultBinding(int32_t slot) {
diff --git a/libultraship/libultraship/SDLController.h b/libultraship/libultraship/SDLController.h
index ae239a2f1..e5d24c946 100644
--- a/libultraship/libultraship/SDLController.h
+++ b/libultraship/libultraship/SDLController.h
@@ -31,6 +31,7 @@ namespace Ship {
void CreateDefaultBinding(int32_t slot) override;
private:
+ std::string ControllerName = "Unknown";
SDL_GameController* Cont;
int physicalSlot;
bool supportsGyro;
diff --git a/libultraship/libultraship/SwitchImpl.cpp b/libultraship/libultraship/SwitchImpl.cpp
new file mode 100644
index 000000000..321b40648
--- /dev/null
+++ b/libultraship/libultraship/SwitchImpl.cpp
@@ -0,0 +1,286 @@
+#ifdef __SWITCH__
+#include "SwitchImpl.h"
+#include
+#include
+#include "SwitchPerformanceProfiles.h"
+#include "Cvar.h"
+#include "Hooks.h"
+
+extern "C" s32 CVar_GetS32(const char* name, s32 defaultValue);
+extern "C" void CVar_SetS32(const char* name, s32 value);
+
+#define DOCKED_MODE 1
+#define HANDHELD_MODE 0
+
+static AppletHookCookie applet_hook_cookie;
+static bool isRunning = true;
+static bool hasFocus = true;
+
+void DetectAppletMode();
+
+static void on_applet_hook(AppletHookType hook, void *param);
+
+void Ship::Switch::Init(SwitchPhase phase){
+ switch(phase){
+ case PreInitPhase:
+ DetectAppletMode();
+ break;
+ case PostInitPhase:
+ appletInitializeGamePlayRecording();
+ #ifdef DEBUG
+ socketInitializeDefault();
+ nxlinkStdio();
+ #endif
+ appletSetGamePlayRecordingState(true);
+ appletHook(&applet_hook_cookie, on_applet_hook, NULL);
+ appletSetFocusHandlingMode(AppletFocusHandlingMode_NoSuspend);
+ if (!hosversionBefore(8, 0, 0)) {
+ clkrstInitialize();
+ }
+ break;
+ }
+}
+
+void Ship::Switch::Exit(){
+#ifdef DEBUG
+ socketExit();
+#endif
+ clkrstExit();
+ appletSetGamePlayRecordingState(false);
+}
+
+void Ship::Switch::SetupFont(ImFontAtlas* fonts) {
+ plInitialize(PlServiceType_System);
+ static PlFontData stdFontData, extFontData;
+
+ PlFontData fonts_std;
+ PlFontData fonts_ext;
+
+ plGetSharedFontByType(&fonts_std, PlSharedFontType_Standard);
+ plGetSharedFontByType(&fonts_ext, PlSharedFontType_NintendoExt);
+
+ ImFontConfig config;
+ config.FontDataOwnedByAtlas = false;
+
+ strcpy(config.Name, "Nintendo Standard");
+ fonts->AddFontFromMemoryTTF (fonts_std.address, fonts_std.size, 24.0f, &config, fonts->GetGlyphRangesCyrillic());
+
+ strcpy(config.Name, "Nintendo Ext");
+ static const ImWchar ranges[] =
+ {
+ 0xE000, 0xE06B,
+ 0xE070, 0xE07E,
+ 0xE080, 0xE099,
+ 0xE0A0, 0xE0BA,
+ 0xE0C0, 0xE0D6,
+ 0xE0E0, 0xE0F5,
+ 0xE100, 0xE105,
+ 0xE110, 0xE116,
+ 0xE121, 0xE12C,
+ 0xE130, 0xE13C,
+ 0xE140, 0xE14D,
+ 0xE150, 0xE153,
+ 0,
+ };
+
+ fonts->AddFontFromMemoryTTF (fonts_ext.address, fonts_ext.size, 24.0f, &config, ranges);
+ fonts->Build ();
+
+ plExit();
+}
+
+bool Ship::Switch::IsRunning(){
+ return isRunning;
+}
+
+void Ship::Switch::GetDisplaySize(int *width, int *height) {
+ switch (appletGetOperationMode()) {
+ case DOCKED_MODE:
+ *width = 1920;
+ *height = 1080;
+ break;
+ case HANDHELD_MODE:
+ *width = 1280;
+ *height = 720;
+ break;
+ }
+}
+
+void Ship::Switch::ApplyOverclock(void) {
+ SwitchProfiles perfMode = (SwitchProfiles) CVar_GetS32("gSwitchPerfMode", (int) Ship::MAXIMUM);
+
+ if (perfMode >= 0 && perfMode <= Ship::POWERSAVINGM3) {
+ if (hosversionBefore(8, 0, 0)) {
+ pcvSetClockRate(PcvModule_CpuBus, SWITCH_CPU_SPEEDS_VALUES[ perfMode ]);
+ } else {
+ ClkrstSession session = {0};
+ clkrstOpenSession(&session, PcvModuleId_CpuBus, 3);
+ clkrstSetClockRate(&session, SWITCH_CPU_SPEEDS_VALUES[ perfMode ]);
+ clkrstCloseSession(&session);
+ }
+ }
+}
+
+struct Star {
+ SDL_Rect* rect;
+ float speed;
+ int layer;
+ int8_t color[3];
+};
+
+std::vector stars;
+
+void Ship::Switch::PrintErrorMessageToScreen(const char *str, ...) {
+
+ if (SDL_Init(SDL_INIT_VIDEO) < 0)
+ return;
+
+ int width, height;
+ Uint64 now, last, deltaTime;
+ GetDisplaySize(&width, &height);
+
+ SDL_Window* win = SDL_CreateWindow("Switch-Error", 0, 0, width, height, 0);
+ SDL_Renderer* renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
+
+ va_list args;
+ va_start(args, str);
+ vprintf(str, args);
+ va_end(args);
+
+ int layers = 9;
+
+ for(int layer = 0; layer < layers; layer++) {
+ for(int i = 0; i < 100; i++) {
+ srand(time(0));
+
+ int brightness = 50 - layer * (rand() * 5);
+ SDL_Rect rect;
+ rect.x = rand() % width;
+ rect.y = i*i;
+ rect.w = rand() % 20;
+ rect.h = rand() % 20;
+
+ stars.push_back(new Star{
+ &rect,
+ 0.03f,
+ layer,
+ {
+ 120 + brightness,
+ 120 + brightness,
+ 120 + brightness
+ }
+ });
+ }
+ }
+
+ while(appletMainLoop()){
+ SDL_Event e;
+ if ( SDL_PollEvent(&e) ) {
+ if (e.type == SDL_QUIT)
+ break;
+ }
+
+ last = now;
+ now = SDL_GetPerformanceCounter();
+
+ deltaTime = (double)((now - last) * 1000 / (double) SDL_GetPerformanceFrequency() );
+
+ SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
+ SDL_RenderClear(renderer);
+
+ for(int i = 0; i < stars.size(); i++){
+ Star* star = stars[i];
+
+ if(star->rect->x >= width){
+ star->rect->x = -star->rect->w;
+ }
+
+ star->rect->x += 1;
+ // star->rect->y += (cos((star->rect->x / star->layer)) * .9f ) / 16;
+ SDL_SetRenderDrawColor(renderer, star->color[0], star->color[1], star->color[2], 255);
+ SDL_RenderFillRect( renderer, star->rect );
+ }
+
+ SDL_RenderPresent(renderer);
+ SDL_Delay(0);
+ }
+
+}
+
+static void on_applet_hook(AppletHookType hook, void *param) {
+ AppletFocusState focus_state;
+
+ /* Exit request */
+ switch (hook) {
+ case AppletHookType_OnExitRequest:
+ isRunning = false;
+ break;
+
+ /* Focus state*/
+ case AppletHookType_OnFocusState:
+ focus_state = appletGetFocusState();
+ hasFocus = focus_state == AppletFocusState_InFocus;
+
+ if (!hasFocus) {
+ if (hosversionBefore(8, 0, 0)) {
+ pcvSetClockRate(PcvModule_CpuBus, SWITCH_CPU_SPEEDS_VALUES[ Ship::STOCK ]);
+ } else {
+ ClkrstSession session = {0};
+ clkrstOpenSession(&session, PcvModuleId_CpuBus, 3);
+ clkrstSetClockRate(&session, SWITCH_CPU_SPEEDS_VALUES[ Ship::STOCK ]);
+ clkrstCloseSession(&session);
+ }
+ } else
+ Ship::Switch::ApplyOverclock();
+ break;
+
+ /* Performance mode */
+ case AppletHookType_OnPerformanceMode:
+ Ship::Switch::ApplyOverclock();
+ break;
+ default: break;
+ }
+}
+
+const char* RandomTexts[] = {
+ "Psst, don't forget to blame Melon",
+ "Potsanity when?",
+ "Why are you acting so random?",
+ "Enough! My ship sails in the morning",
+ "Do you want 2 or 7 of those?",
+ "Lamp oil, rope, bombs you want it, it's yours my friend as long as you have enough rupees",
+ "You can build it yourself",
+ "Descargar para android",
+ "Made with <3 by the Harbour Masters!",
+ "They say that Kenix is not a developer",
+ "Squadala we're off",
+ "They say one once saw an equals not get set equals",
+ "This is the port all true gamers dock at"
+ "Enhancements? Times Savers? Cheats? You want them? They're yours my friend!",
+ "They say you gotta have the BIIIIG salad",
+ "They say Louis stopped working on the imports so he can focus on the exports",
+ "They say ZAPD is good software",
+};
+
+void DetectAppletMode() {
+ AppletType at = appletGetAppletType();
+ if (at == AppletType_Application || at == AppletType_SystemApplication)
+ return;
+
+ srand(time(0));
+ Ship::Switch::PrintErrorMessageToScreen(
+ "\x1b[2;2HYou've launched the Ship while in Applet mode."
+ "\x1b[4;2HPlease relaunch while in full-memory mode."
+ "\x1b[5;2HHold R when opening any game to enter HBMenu."
+ "\x1b[44;2H%s."
+ , RandomTexts[rand() % 25]);
+}
+
+void Ship::Switch::ThrowMissingOTR(std::string OTRPath){
+ Ship::Switch::PrintErrorMessageToScreen(
+ "\x1b[2;2HYou've launched the Ship without the OTR file."
+ "\x1b[4;2HPlease relaunch making sure %s exists."
+ "\x1b[44;2H%s."
+ , OTRPath.c_str(), RandomTexts[rand() % 25]);
+}
+#endif
\ No newline at end of file
diff --git a/libultraship/libultraship/SwitchImpl.h b/libultraship/libultraship/SwitchImpl.h
new file mode 100644
index 000000000..af592413a
--- /dev/null
+++ b/libultraship/libultraship/SwitchImpl.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include
+#include
+
+#include "Lib/ImGui/imgui.h"
+#include "SwitchPerformanceProfiles.h"
+
+namespace Ship {
+ enum SwitchProfiles {
+ MAXIMUM,
+ HIGH,
+ BOOST,
+ STOCK,
+ POWERSAVINGM1,
+ POWERSAVINGM2,
+ POWERSAVINGM3
+ };
+
+ enum SwitchPhase {
+ PreInitPhase,
+ PostInitPhase
+ };
+
+ class Switch {
+ public:
+ static void Init(SwitchPhase phase);
+ static void Exit();
+ static void SetupFont(ImFontAtlas* fonts);
+ static bool IsRunning();
+ static void GetDisplaySize(int *width, int *height);
+ static void ApplyOverclock();
+ static void ThrowMissingOTR(std::string OTRPath);
+ static void PrintErrorMessageToScreen(const char *str, ...);
+ };
+};
\ No newline at end of file
diff --git a/libultraship/libultraship/SwitchPerformanceProfiles.h b/libultraship/libultraship/SwitchPerformanceProfiles.h
new file mode 100644
index 000000000..1cb930c0a
--- /dev/null
+++ b/libultraship/libultraship/SwitchPerformanceProfiles.h
@@ -0,0 +1,21 @@
+#pragma once
+
+static const char *SWITCH_CPU_PROFILES[] = {
+ "Maximum Performance",
+ "High Performance",
+ "Boost Performance",
+ "Stock Performance",
+ "Powersaving Mode 1",
+ "Powersaving Mode 2",
+ "Powersaving Mode 3",
+};
+
+static unsigned SWITCH_CPU_SPEEDS_VALUES[] = {
+ 1785000000,
+ 1581000000,
+ 1224000000,
+ 1020000000,
+ 918000000,
+ 816000000,
+ 714000000
+};
\ No newline at end of file
diff --git a/libultraship/libultraship/Window.cpp b/libultraship/libultraship/Window.cpp
index 9d28ecf5e..9957ebc48 100644
--- a/libultraship/libultraship/Window.cpp
+++ b/libultraship/libultraship/Window.cpp
@@ -28,6 +28,7 @@
#include
#include "Hooks.h"
#include "Console.h"
+#include "Cvar.h"
#include
@@ -35,7 +36,6 @@ extern "C" {
struct OSMesgQueue;
uint8_t __osMaxControllers = MAXCONTROLLERS;
- uint8_t __enableGameInput = 1;
int32_t osContInit(OSMesgQueue* mq, uint8_t* controllerBits, OSContStatus* status) {
*controllerBits = 0;
@@ -45,6 +45,7 @@ extern "C" {
exit(EXIT_FAILURE);
}
+ #ifndef __SWITCH__
const char* controllerDb = "gamecontrollerdb.txt";
int mappingsAdded = SDL_GameControllerAddMappingsFromFile(controllerDb);
if (mappingsAdded >= 0) {
@@ -52,6 +53,7 @@ extern "C" {
} else {
SPDLOG_ERROR("Failed add SDL game controller mappings from \"{}\" ({})", controllerDb, SDL_GetError());
}
+ #endif
Ship::Window::ControllerApi->Init(controllerBits);
@@ -72,7 +74,7 @@ extern "C" {
pad->gyro_x = 0;
pad->gyro_y = 0;
- if (__enableGameInput) {
+ if (!CVar_GetS32("gOpenMenuBar", 0)) {
Ship::Window::ControllerApi->WriteToPad(pad);
}
@@ -302,7 +304,6 @@ namespace Ship {
void Window::MainLoop(void (*MainFunction)(void)) {
WmApi->main_loop(MainFunction);
}
-
bool Window::KeyUp(int32_t dwScancode) {
std::shared_ptr pConf = GlobalCtx2::GetInstance()->GetConfig();
@@ -314,7 +315,7 @@ namespace Ship {
//if (dwScancode == Ship::stoi(Conf["KEYBOARD SHORTCUTS"]["KEY_CONSOLE"])) {
// ToggleConsole();
//}
-
+
lastScancode = -1;
bool bIsProcessed = false;
diff --git a/libultraship/libultraship/WindowShim.cpp b/libultraship/libultraship/WindowShim.cpp
index 4469c5c29..ca9357575 100644
--- a/libultraship/libultraship/WindowShim.cpp
+++ b/libultraship/libultraship/WindowShim.cpp
@@ -22,7 +22,7 @@ void SetWindowManager(struct GfxWindowManagerAPI** WmApi, struct GfxRenderingAPI
// First set default
#ifdef ENABLE_OPENGL
*RenderingApi = &gfx_opengl_api;
- #if defined(__linux__)
+ #if defined(__linux__) && defined(X11_SUPPORTED)
// LINUX_TODO:
// *WmApi = &gfx_glx;
*WmApi = &gfx_sdl;
@@ -51,7 +51,7 @@ void SetWindowManager(struct GfxWindowManagerAPI** WmApi, struct GfxRenderingAPI
*RenderingApi = &gfx_opengl_api;
*WmApi = &gfx_sdl;
}
-#ifdef __linux__
+#if defined(__linux__) && defined(X11_SUPPORTED)
if (gfx_backend == "glx") {
*RenderingApi = &gfx_opengl_api;
*WmApi = &gfx_glx;
diff --git a/libultraship/libultraship/libultraship.vcxproj b/libultraship/libultraship/libultraship.vcxproj
index 920f6442f..9c759f85a 100644
--- a/libultraship/libultraship/libultraship.vcxproj
+++ b/libultraship/libultraship/libultraship.vcxproj
@@ -450,12 +450,6 @@
-
-
- {02d10590-9542-3f55-aaf8-6055677e2a2a}
- false
-
-
diff --git a/soh/Makefile b/soh/Makefile
index b05321a60..2c0f9ff31 100644
--- a/soh/Makefile
+++ b/soh/Makefile
@@ -179,7 +179,7 @@ all:
$(MAKE) $(TARGET)
setup:
- cd ../OTRExporter && python3 extract_baserom.py
+ cd ../OTRExporter
$(MAKE) mpq
mpq:
diff --git a/soh/Makefile.switch b/soh/Makefile.switch
new file mode 100644
index 000000000..10eaaebab
--- /dev/null
+++ b/soh/Makefile.switch
@@ -0,0 +1,280 @@
+#---------------------------------------------------------------------------------
+.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.
+#---------------------------------------------------------------------------------
+TARGET := $(notdir $(CURDIR))
+BUILD := build
+SOURCES := switch
+DATA :=
+INCLUDES := \
+ . \
+ assets \
+ build \
+ include \
+ src \
+ ../ZAPDTR/ZAPDUtils \
+ ../libultraship/libultraship \
+ ../libultraship/libultraship/Lib/spdlog/include \
+ ../libultraship/libultraship/Lib/Fast3D/U64 \
+ ../libultraship/libultraship/Lib/Fast3D/U64/PR
+
+#-------------------------------------------------------------------------------
+# source files
+#-------------------------------------------------------------------------------
+SOURCEFILES_C := \
+ $(shell find soh -type f -name "*.c") \
+ $(shell find src/boot -type f -name "*.c") \
+ $(shell find src/buffers -type f -name "*.c") \
+ $(shell find src/code -type f -name "*.c") \
+ $(shell find src/overlays -type f -name "*.c") \
+ src/libultra/gu/coss.c \
+ src/libultra/gu/guLookAt.c \
+ src/libultra/gu/guLookAtHilite.c \
+ src/libultra/gu/guPerspectiveF.c \
+ src/libultra/gu/guPosition.c \
+ src/libultra/gu/guS2DInitBg.c \
+ src/libultra/gu/ortho.c \
+ src/libultra/gu/rotate.c \
+ src/libultra/gu/sins.c \
+ src/libultra/gu/sintable.c \
+ src/libultra/libc/sprintf.c
+
+SOURCEFILES_CPP := \
+ $(shell find soh -type f -name "*.cpp")
+#---------------------------------------------------------------------------------
+# app info
+#---------------------------------------------------------------------------------
+
+APP_TITLE := Ship of Harkinian
+APP_AUTHOR := Harbour Masters
+APP_VERSION := Rachael-Alfa
+
+#---------------------------------------------------------------------------------
+# options for code generation
+#---------------------------------------------------------------------------------
+ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE -ffast-math -O3
+
+CFLAGS := -ffunction-sections \
+ $(ARCH) $(DEFINES)
+
+CFLAGS += $(INCLUDE) -D__SWITCH__ \
+ -DSPDLOG_NO_THREAD_ID \
+ -DSTBI_NO_THREAD_LOCALS \
+ `sdl2-config --cflags`
+
+CXXFLAGS := $(CFLAGS) -std=gnu++20 -fpermissive
+CFLAGS += -std=gnu11
+
+# disable some warnings
+CFLAGS += -Wno-incompatible-pointer-types -Wno-int-conversion \
+ -Wno-builtin-declaration-mismatch -Wno-implicit-function-declaration \
+ -Wno-stringop-overflow -Wno-discarded-qualifiers -Wno-switch-unreachable
+
+ASFLAGS := -g $(ARCH)
+LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
+
+STATIC_LIBS := $(SOH_TOP_DIR)/libultraship/lib/libultraship.a \
+ $(SOH_TOP_DIR)/ZAPDTR/ZAPDUtils/lib/libZAPDUtils.a \
+ $(SOH_TOP_DIR)/ZAPDTR/ZAPDUtils/lib/libZAPDUtils.a \
+ $(SOH_TOP_DIR)/StormLib/nxbuild/libstorm.a \
+
+LIBS := -L$(SOH_TOP_DIR)/StormLib/nxbuild/ -lultraship -lZAPDUtils -lstorm -lz -lbz2 -lnx -lglad -lglapi -ldrm_nouveau -lm `sdl2-config --libs`
+
+#---------------------------------------------------------------------------------
+# list of directories containing libraries, this must be the top level containing
+# include and lib
+#---------------------------------------------------------------------------------
+LIBDIRS := $(PORTLIBS) $(LIBNX) $(SOH_TOP_DIR)/StormLib/nxbuild $(SOH_TOP_DIR)/libultraship $(SOH_TOP_DIR)/ZAPDTR/ZAPDUtils
+
+#---------------------------------------------------------------------------------
+# 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)) \
+ $(foreach sf,$(SOURCEFILES_C),$(CURDIR)/$(dir $(sf))) \
+ $(foreach sf,$(SOURCEFILES_CPP),$(CURDIR)/$(dir $(sf)))
+
+export DEPSDIR := $(CURDIR)/$(BUILD)
+
+CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) \
+ $(foreach f,$(SOURCEFILES_C),$(notdir $(f)))
+CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) \
+ $(foreach f,$(SOURCEFILES_CPP),$(notdir $(f)))
+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.switch
+
+#---------------------------------------------------------------------------------
+clean:
+ @echo clean ...
+ifeq ($(strip $(APP_JSON)),)
+ @rm -fr $(BUILD) $(TARGET).nro $(TARGET).nacp $(TARGET).elf
+else
+ @rm -fr $(BUILD) $(TARGET).nsp $(TARGET).nso $(TARGET).npdm $(TARGET).elf
+endif
+
+
+#---------------------------------------------------------------------------------
+else
+.PHONY: all
+
+DEPENDS := $(OFILES:.o=.d)
+
+#---------------------------------------------------------------------------------
+# main targets
+#---------------------------------------------------------------------------------
+ifeq ($(strip $(APP_JSON)),)
+
+all : $(OUTPUT).nro
+
+ifeq ($(strip $(NO_NACP)),)
+$(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp
+else
+$(OUTPUT).nro : $(OUTPUT).elf
+endif
+
+else
+
+all : $(OUTPUT).nsp
+
+$(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm
+
+$(OUTPUT).nso : $(OUTPUT).elf
+
+endif
+
+$(OUTPUT).elf : $(OFILES) \
+ $(STATIC_LIBS)
+
+$(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
+#---------------------------------------------------------------------------------------
\ No newline at end of file
diff --git a/soh/icon.jpg b/soh/icon.jpg
new file mode 100644
index 000000000..3a855753b
Binary files /dev/null and b/soh/icon.jpg differ
diff --git a/soh/include/functions.h b/soh/include/functions.h
index 72fd6e98c..b185519f4 100644
--- a/soh/include/functions.h
+++ b/soh/include/functions.h
@@ -60,7 +60,7 @@ void Locale_ResetRegion(void);
u32 func_80001F48(void);
u32 func_80001F8C(void);
u32 Locale_IsRegionNative(void);
-#ifndef __APPLE__
+#if !defined(__APPLE__) && !defined(__SWITCH__)
void __assert(const char* exp, const char* file, s32 line);
#endif
void isPrintfInit(void);
@@ -1872,7 +1872,7 @@ void FaultDrawer_SetCharPad(s8, s8);
void FaultDrawer_SetCursor(s32, s32);
void FaultDrawer_FillScreen();
void* FaultDrawer_FormatStringFunc(void*, const char*, u32);
-void FaultDrawer_VPrintf(const char*, char*);
+void FaultDrawer_VPrintf(const char*, va_list);
void FaultDrawer_Printf(const char*, ...);
void FaultDrawer_DrawText(s32, s32, const char*, ...);
void FaultDrawer_SetDrawerFB(void*, u16, u16);
diff --git a/soh/include/z64audio.h b/soh/include/z64audio.h
index 3911bb6c4..c765aa4ed 100644
--- a/soh/include/z64audio.h
+++ b/soh/include/z64audio.h
@@ -783,6 +783,8 @@ typedef struct {
/* 0x0E */ u8 ttl; // duration after which the DMA can be discarded
} SampleDma; // size = 0x10
+#include
+
typedef struct {
/* 0x0000 */ char unk_0000;
/* 0x0001 */ s8 numSynthesisReverbs;
diff --git a/soh/soh/Enhancements/bootcommands.c b/soh/soh/Enhancements/bootcommands.c
index 6dc6b18b4..c766049ae 100644
--- a/soh/soh/Enhancements/bootcommands.c
+++ b/soh/soh/Enhancements/bootcommands.c
@@ -44,11 +44,6 @@ void BootCommands_ParseBootArgs(s32 argc, char** argv)
}
}
}
-
- for (i = 0; i < argc; i++)
- DebugArena_Free(argv[i]);
-
- //DebugArena_Free(argv);
}
/*
diff --git a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp
index 64281ddd5..66b9b8939 100644
--- a/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp
+++ b/soh/soh/Enhancements/cosmetics/CosmeticsEditor.cpp
@@ -8,6 +8,7 @@
#include