Created
June 10, 2024 12:39
-
-
Save allquixotic/0530bde2247415a676288e8f62592a4d to your computer and use it in GitHub Desktop.
MacOS run_bepinex.sh for Valheim
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# BepInEx start script | |
# | |
# Run the script to start the game with BepInEx enabled | |
# | |
# There are two ways to use this script | |
# | |
# 1. Via CLI: Run ./run_bepinex.sh <path to game> [doorstop arguments] [game arguments] | |
# 2. Via config: edit the options below and run ./run.sh without any arguments | |
# Required to tell MacOS Gatekeeper to allow libdoorstop to run while unsigned | |
xattr -d com.apple.quarantine libdoorstop.dylib | |
# 0 is false, 1 is true | |
# LINUX: name of Unity executable | |
# MACOS: name of the .app directory | |
executable_name="valheim.app" | |
# All of the below can be overriden with command line args | |
# General Config Options | |
# Enable Doorstop? | |
enabled="1" | |
# Path to the assembly to load and execute | |
# NOTE: The entrypoint must be of format `static void Doorstop.Entrypoint.Start()` | |
#target_assembly="BepInEx/core/BepInEx.Unity.Mono.Preloader.dll" | |
target_assembly="BepInEx/core/BepInEx.Preloader.dll" | |
# If enabled, DOORSTOP_DISABLE env var value is ignored | |
# USE THIS ONLY WHEN ASKED TO OR YOU KNOW WHAT THIS MEANS | |
ignore_disable_switch="0" | |
# Mono Options | |
# Overrides default Mono DLL search path | |
# Sometimes it is needed to instruct Mono to seek its assemblies from a different path | |
# (e.g. mscorlib is stripped in original game) | |
# This option causes Mono to seek mscorlib and core libraries from a different folder before Managed | |
# Original Managed folder is added as a secondary folder in the search path | |
# To specify multiple paths, separate them with colons (:) | |
dll_search_path_override="BepInEx/core" | |
# If 1, Mono debugger server will be enabled | |
debug_enable="0" | |
# When debug_enabled is 1, this option specifies whether Doorstop should initialize the debugger server | |
# If you experience crashes when starting the debugger on debug UnityPlayer builds, try setting this to 0 | |
debug_start_server="0" | |
# When debug_enabled is 1, specifies the address to use for the debugger server | |
debug_address="127.0.0.1:10000" | |
# If 1 and debug_enabled is 1, Mono debugger server will suspend the game execution until a debugger is attached | |
debug_suspend="0" | |
# CoreCLR options (IL2CPP) | |
# Path to coreclr shared library WITHOUT THE EXTENSION that contains the CoreCLR runtime | |
coreclr_path="" | |
# Path to the directory containing the managed core libraries for CoreCLR (mscorlib, System, etc.) | |
corlib_dir="" | |
################################################################################ | |
# Everything past this point is the actual script | |
# Special case: program is launched via Steam | |
# In that case rerun the script via their bootstrapper to ensure Steam overlay works | |
if [ "$2" = "SteamLaunch" ]; then | |
# Conceptually: exec "$1" "$2" "$3" "$4" "$0" "rest of $@" | |
# But newer versions of Steam interleave the $1..$4 with some "--" arguments, so preserve them as well | |
# Bash has array subscripting, but POSIX sh doesn't, so avoid it | |
to_rotate=4 | |
rotated=0 | |
while [ $((to_rotate-=1)) -ge 0 ]; do | |
while [ "z$1" = "z--" ]; do | |
set -- "$@" "$1" | |
shift | |
rotated=$((rotated+1)) | |
done | |
set -- "$@" "$1" | |
shift | |
rotated=$((rotated+1)) | |
done | |
to_rotate=$(($# - rotated)) | |
set -- "$@" "$0" | |
while [ $((to_rotate-=1)) -ge 0 ]; do | |
set -- "$@" "$1" | |
shift | |
done | |
exec "$@" | |
fi | |
# Handle first param being executable name | |
if [ -x "$1" ] ; then | |
executable_name="$1" | |
echo "Target executable: $1" | |
shift | |
fi | |
if [ -z "${executable_name}" ] || [ ! -x "${executable_name}" ]; then | |
echo "Please set executable_name to a valid name in a text editor or as the first command line parameter" | |
exit 1 | |
fi | |
# Use POSIX-compatible way to get the directory of the executable | |
a="/$0"; a=${a%/*}; a=${a#/}; a=${a:-.}; BASEDIR=$(cd "$a" || exit; pwd -P) | |
arch="" | |
executable_path="" | |
lib_extension="" | |
# Set executable path and the extension to use for the libdoorstop shared object | |
os_type="$(uname -s)" | |
case ${os_type} in | |
Linux*) | |
executable_path="${executable_name}" | |
# Handle relative paths | |
if ! echo "$executable_path" | grep "^/.*$"; then | |
executable_path="${BASEDIR}/${executable_path}" | |
fi | |
lib_extension="so" | |
;; | |
Darwin*) | |
real_executable_name="${executable_name}" | |
# Handle relative directories | |
if ! echo "$real_executable_name" | grep "^/.*$"; then | |
real_executable_name="${BASEDIR}/${real_executable_name}" | |
fi | |
# If we're not even an actual executable, check .app Info for actual executable | |
if ! echo "$real_executable_name" | grep "^.*\.app/Contents/MacOS/.*"; then | |
# Add .app to the end if not given | |
if ! echo "$real_executable_name" | grep "^.*\.app$"; then | |
real_executable_name="${real_executable_name}.app" | |
fi | |
inner_executable_name=$(defaults read "${real_executable_name}/Contents/Info" CFBundleExecutable) | |
executable_path="${real_executable_name}/Contents/MacOS/${inner_executable_name}" | |
else | |
executable_path="${executable_name}" | |
fi | |
lib_extension="dylib" | |
;; | |
*) | |
# alright whos running games on freebsd | |
echo "Unknown operating system ($(uname -s))" | |
echo "Make an issue at https://github.com/NeighTools/UnityDoorstop" | |
exit 1 | |
;; | |
esac | |
abs_path() { | |
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")" | |
} | |
_readlink() { | |
# relative links with readlink (without -f) do not preserve the path info | |
ab_path="$(abs_path "$1")" | |
link="$(readlink "${ab_path}")" | |
case $link in | |
/*);; | |
*) link="$(dirname "$ab_path")/$link";; | |
esac | |
echo "$link" | |
} | |
resolve_executable_path () { | |
e_path="$(abs_path "$1")" | |
while [ -L "${e_path}" ]; do | |
e_path=$(_readlink "${e_path}"); | |
done | |
echo "${e_path}" | |
} | |
# Get absolute path of executable and show to user | |
executable_path=$(resolve_executable_path "${executable_path}") | |
echo "${executable_path}" | |
# Figure out the arch of the executable with file | |
file_out="$(LD_PRELOAD="" file -b "${executable_path}")" | |
# case "${file_out}" in | |
# *64-bit*) | |
# arch="x64" | |
# ;; | |
# *32-bit*) | |
# arch="x86" | |
# ;; | |
# *) | |
# echo "The executable \"${executable_path}\" is not compiled for x86 or x64 (might be ARM?)" | |
# echo "If you think this is a mistake (or would like to encourage support for other architectures)" | |
# echo "Please make an issue at https://github.com/NeighTools/UnityDoorstop" | |
# echo "Got: ${file_out}" | |
# exit 1 | |
# ;; | |
# esac | |
# Helper to convert common boolean strings into just 0 and 1 | |
doorstop_bool() { | |
case "$1" in | |
TRUE|true|t|T|1|Y|y|yes) | |
echo "1" | |
;; | |
FALSE|false|f|F|0|N|n|no) | |
echo "0" | |
;; | |
esac | |
} | |
# Read from command line | |
while :; do | |
case "$1" in | |
--doorstop_enabled) | |
enabled="$(doorstop_bool "$2")" | |
shift | |
;; | |
--doorstop_target_assembly) | |
target_assembly="$2" | |
shift | |
;; | |
--doorstop-mono-dll-search-path-override) | |
dll_search_path_override="$2" | |
shift | |
;; | |
--doorstop-mono-debug-enabled) | |
debug_enable="$(doorstop_bool "$2")" | |
shift | |
;; | |
--doorstop-mono-debug-start-server) | |
debug_start_server="$(doorstop_bool "$2")" | |
shift | |
;; | |
--doorstop-mono-debug-suspend) | |
debug_suspend="$(doorstop_bool "$2")" | |
shift | |
;; | |
--doorstop-mono-debug-address) | |
debug_address="$2" | |
shift | |
;; | |
--doorstop-clr-runtime-coreclr-path) | |
coreclr_path="$2" | |
shift | |
;; | |
--doorstop-clr-corlib-dir) | |
corlib_dir="$2" | |
shift | |
;; | |
*) | |
if [ -z "$1" ]; then | |
break | |
fi | |
rest_args="$rest_args $1" | |
;; | |
esac | |
shift | |
done | |
# Move variables to environment | |
export DOORSTOP_ENABLED="1" | |
export DOORSTOP_TARGET_ASSEMBLY="$target_assembly" | |
export DOORSTOP_IGNORE_DISABLED_ENV="$ignore_disable_switch" | |
export DOORSTOP_MONO_DLL_SEARCH_PATH_OVERRIDE="$dll_search_path_override" | |
export DOORSTOP_MONO_DEBUG_ENABLED="$debug_enable" | |
export DOORSTOP_MONO_DEBUG_START_SERVER="$debug_start_server" | |
export DOORSTOP_MONO_DEBUG_ADDRESS="$debug_address" | |
export DOORSTOP_MONO_DEBUG_SUSPEND="$debug_suspend" | |
export DOORSTOP_CLR_RUNTIME_CORECLR_PATH="$coreclr_path.$lib_extension" | |
export DOORSTOP_CLR_CORLIB_DIR="$corlib_dir" | |
# Final setup | |
doorstop_directory="${BASEDIR}/" | |
doorstop_name="libdoorstop.dylib" | |
export LD_LIBRARY_PATH="${doorstop_directory}:${corlib_dir}:${LD_LIBRARY_PATH}" | |
if [ -z "$LD_PRELOAD" ]; then | |
export LD_PRELOAD="${doorstop_name}" | |
else | |
export LD_PRELOAD="${doorstop_name}:${LD_PRELOAD}" | |
fi | |
export DYLD_LIBRARY_PATH="${doorstop_directory}" | |
if [ -z "$DYLD_INSERT_LIBRARIES" ]; then | |
export DYLD_INSERT_LIBRARIES="${doorstop_name}" | |
else | |
export DYLD_INSERT_LIBRARIES="${doorstop_name}:${DYLD_INSERT_LIBRARIES}" | |
fi | |
# shellcheck disable=SC2086 | |
#exec "$executable_path" $rest_args | |
# Wrap the launch command in `arch -x86_64`, which forces the game to run in x86_64 mode (libdoorstop does not exist for Apple Silicon) | |
current_path=$(pwd) | |
exports="export LD_LIBRARY_PATH=\"$LD_LIBRARY_PATH\";export LD_PRELOAD=$LD_PRELOAD;export DYLD_LIBRARY_PATH=\"$DYLD_LIBRARY_PATH\";export DYLD_INSERT_LIBRARIES=\"$DYLD_INSERT_LIBRARIES\"" | |
cdir="cd \"$current_path\"" | |
exec="\"${executable_path}\"" | |
a="\"$rest_args\"" | |
launch="arch;$cdir;pwd;$exports;$exec $a" | |
echo "Wrapping x86_64 Launch Command: $launch" | |
arch -x86_64 zsh -c "$launch" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment