├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── fnaify ├── fnaify.1 └── fnaify.dllmap.config /.gitignore: -------------------------------------------------------------------------------- 1 | CVS 2 | .#* 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2020 Thomas Frohwein 2 | Copyright (c) 2018 Mariusz Zaborski 3 | 4 | Permission to use, copy, modify, and distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PREFIX ?= /usr/local 2 | 3 | .PHONY: install 4 | install: 5 | mkdir -p $(DESTDIR)$(PREFIX)/share/fnaify/ 6 | cp fnaify $(DESTDIR)$(PREFIX)/bin/ 7 | cp fnaify.dllmap.config $(DESTDIR)$(PREFIX)/share/fnaify/ 8 | cp fnaify.1 $(DESTDIR)$(PREFIX)/man/man1/ 9 | 10 | readme: fnaify.1 11 | mandoc -mdoc -T markdown fnaify.1 > README.md 12 | 13 | .PHONY: uninstall 14 | uninstall: 15 | rm -f $(DESTDIR)$(PREFIX)/bin/fnaify 16 | rm -f $(DESTDIR)$(PREFIX)/share/fnaify/fnaify.dllmap.config 17 | rm -f $(DESTDIR)$(PREFIX)/man/man1/fnaify.1 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | FNAIFY(1) - General Commands Manual 2 | 3 | # NAME 4 | 5 | **fnaify** - run FNA/XNA games on OpenBSD 6 | 7 | # SYNOPSIS 8 | 9 | **fnaify** 10 | \[**-i** | **-y**] 11 | \[**-hnsv**] 12 | \[**-c** *configfile*] 13 | \[**-D** *depdir*] 14 | \[**-d** *gamedir*] 15 | \[**-f** *frameworkfile* | **-F** *frameworkversion*] 16 | \[**-m** *monopath*] 17 | \[*userflags*] 18 | 19 | # DESCRIPTION 20 | 21 | **fnaify** 22 | runs games based on the FNA engine with OpenBSD-native 23 | libraries and its 24 | mono(1) 25 | runtime. 26 | 27 | As of version 2.0, 28 | **fnaify** 29 | has been extended to attempt configuring XNA games as well. 30 | **fnaify** 31 | can be run in 3 basic modes regarding the addition of missing libraries: 32 | restrictive 33 | (default) 34 | , interactive, and permissive. 35 | 36 | As of version 3.0, 37 | **fnaify** 38 | unifies both setup and launch of supported games in one command. 39 | 40 | All games require additional libraries from ports, like SDL2. Some of 41 | them can be found in the fnaify-extralibs package, like libatomstb or 42 | libfmod\_SDL. 43 | 44 | The arguments are as follows: 45 | 46 | **-i** | **-y** 47 | 48 | > The mode determines how 49 | > **fnaify** 50 | > handles situations where compatibility problems are identified that can 51 | > be addressed with drop-in DLL replacements, or where an option needs to 52 | > be selected. 53 | > With 54 | > **-i**, 55 | > **fnaify** 56 | > runs in interactive mode, meaning the user will be prompted in every 57 | > case. 58 | > With 59 | > **-y**, 60 | > **fnaify** 61 | > runs in permissive mode 62 | > (**-y** 63 | > for 64 | > "yes" 65 | > to all) 66 | > . 67 | > This means that any suggested drop-in DLLs will be installed, 68 | > and if different options are possible (like picking among several .exe 69 | > files for the launch script), the first one will be selected 70 | > automatically. 71 | > If neither 72 | > **-i** 73 | > nor 74 | > **-y** 75 | > is specified, 76 | > **fnaify** 77 | > runs in restrictive mode, that is no drop-in DLLs will be installed. 78 | 79 | **-c** *configfile* 80 | 81 | > Optional. Use 82 | > *configfile* 83 | > for the configuration of 84 | > mono(1). 85 | > This sets up dllmap/dllentry settings to use the correct libraries. See 86 | > mono-config(5) 87 | > for details. If this option is omitted, 88 | > **fnaify** 89 | > looks first for 90 | > *~/.config/fnaify/fnaify.dllmap.config* 91 | > and then for 92 | > */usr/local/share/fnaify/fnaify.dllmap.config*. 93 | > If neither one is found, 94 | > **fnaify** 95 | > creates 96 | > *~/.config/fnaify/fnaify.dllmap.config* 97 | > with default settings. 98 | 99 | **-D** *depdir* 100 | 101 | > Add 102 | > *depdir* 103 | > to the directories to search for native library dependencies. 104 | > A directory specified this way will be searched 105 | > *before* 106 | > the default locations 107 | > (*/usr/local/lib* etc.). 108 | 109 | **-d** *gamedir* 110 | 111 | > Path to the game's directory 112 | > (defaults to the current working directory). 113 | 114 | **-F** *frameworkversion* 115 | 116 | > Choose a specific framework version to use. 117 | 118 | **-f** *frameworkfile* 119 | 120 | > Framework file to use. Typically 121 | > *FNA.dll* 122 | > or 123 | > *MonoGame.Framework.dll*. 124 | > By default will automatically identify the bundled file in the 125 | > game's directory. 126 | 127 | **-h** 128 | 129 | > Prints help text. 130 | 131 | **-m** *monopath* 132 | 133 | > Add 134 | > *monopath* 135 | > to the directories the 136 | > mono(1) 137 | > runtime will search for DLLs. 138 | 139 | **-n** 140 | 141 | > Skip checks for library dependencies. 142 | 143 | **-s** 144 | 145 | > Force (re-)running setup. 146 | 147 | **-V** 148 | 149 | > Display version of 150 | > **fnaify**. 151 | 152 | **-v** 153 | 154 | > Verbose mode. 155 | 156 | *userflags* 157 | 158 | > Optional. 159 | > Flags that are passed to the game as arguments 160 | 161 | # SUPPORTED GAMES 162 | 163 | Games marked with \[!] may have errors or other significant limitations. 164 | 165 | The Adventures of Shuggy 166 | Akane the Kunoichi 167 | Amazing Princess Sarah \[!] 168 | Apotheon 169 | Apple Jack 1&2 170 | Atom Zombie Smasher 171 | A Virus Named TOM \[!] 172 | Before the Echo \[!] 173 | Bird Assassin 174 | Bleed 175 | Bleed 2 176 | Blossom Tales II: The Minotaur Prince 177 | Breath of Death VII 178 | Brushwood Buddies 179 | Camera Obscura 180 | Capsized 181 | Capsule Force 182 | Celeste (no audio) 183 | Chaos Heart \[!] 184 | Charlie Murder 185 | Chasm 186 | CometStriker 187 | Cryptark 188 | Crystal Project 189 | Cthulhu Saves the World 190 | Curse of the Crescent Isle DX 191 | Dad Quest 192 | Dead Pixels \[!] 193 | Dead Pixels II (Early Access) 194 | Diehard Dungeon 195 | The Dishwasher: Vampire Smile 196 | Draw a Stickman: EPIC 197 | Dust: An Elysian Tail 198 | DwarfCorp 199 | Eagle Island \[!] 200 | Eliza 201 | Escape Goat 202 | Escape Goat 2 203 | EXAPUNKS 204 | FEZ \[!] 205 | Fist Puncher 206 | Flinthook 207 | Flotilla 208 | Gateways 209 | Glitchangels 210 | Grand Class Melee 2 \[!] 211 | Growing Pains 212 | HackNet 213 | Hidden in Plain Sight 214 | Hive 215 | Hyphen 216 | Jon Shafer's At the Gates 217 | LaserCat 218 | Last Call BBS 219 | Little Racers STREET 220 | Mercenary Kings 221 | Miasma: Citizens of Free Thought 222 | Miasma 2: Freedom Uprising \[!] 223 | MidBoss 224 | Mobius Front '83 \[!] 225 | Molek-Syntez 226 | Mount Your Friends 227 | NeuroVoider \[!] 228 | Ninja Warrior 229 | One Finger Death Punch 230 | Opus Magnum 231 | Overdriven Reloaded 232 | Owlboy 233 | Paladin 234 | Penny Arcade's On the Rain-Slick Precipice of Darkness 3 235 | Penny Arcade's On the Rain-Slick Precipice of Darkness 4 236 | Phoenix Force \[!] 237 | PlanetFriend 238 | Press X to Not Die 239 | Rex Rocket 240 | Rogue Legacy 241 | Ruggnar 242 | Salt and Sanctuary 243 | Session Seven 244 | Shenzhen I/O 245 | Shipwreck \[!] 246 | Signs of Life 247 | Skulls of the Shogun 248 | Soulcaster 1 & 2 249 | SpaceChem 250 | SpeedRunners 251 | Stardew Valley \[!] 252 | Steel Assault 253 | Sumico 254 | Super Amazing Wagon Adventure 255 | Super Bernie World 256 | Super Blood Hockey 257 | Super Rad Raygun 258 | Sword of the Stars: The Pit \[!] 259 | Terraria 260 | Timespinner 261 | TowerFall: Ascension 262 | Ultra Hat Dimension 263 | Unexplored 264 | Unholy Heights 265 | The Useful Dead 266 | Weapon of Choice \[!] 267 | Wizorb \[!] 268 | Wyv and Keep 269 | 270 | # FILES 271 | 272 | */usr/local/share/fnaify/fnaify.dllmap.config* 273 | 274 | > Default configuration file to map DLLs to native libraries. 275 | 276 | *~/.config/fnaify/fnaify.dllmap.config* 277 | 278 | > User directory configuration file. Takes precedence if it exists. 279 | > Make sure to keep it up-to-date! 280 | 281 | # EXIT STATUS 282 | 283 | **fnaify** 284 | returns 1 if an error occurred, otherwise 0. 285 | 286 | # EXAMPLES 287 | 288 | Run in permissive mode, suitable to set up most supported games 289 | automatically. 290 | 291 | $ fnaify -y -d path/to/game/directory 292 | 293 | Run in interactive mode. 294 | **fnaify** 295 | will prompt the user if any additional DLLs are recommended, or if a 296 | file needs to be selected for the launch script. 297 | 298 | $ fnaify -i 299 | 300 | # SEE ALSO 301 | 302 | mono(1), 303 | mono-config(5) 304 | 305 | # HISTORY 306 | 307 | The 308 | **fnaify** 309 | utility was originally created in December 2017 by 310 | Thomas Frohwein <[thfr@openbsd.org](mailto:thfr@openbsd.org)>. 311 | 312 | # RELEASE HISTORY 313 | 314 | 3\.1 315 | 316 | > Stop removing Steamworks.NET.dll. Instead, rely on other lower level 317 | > native libraries (CSteamworks, libsteam\_api). Add flag 318 | > **-n** 319 | > to skip library checks. 320 | 321 | 3\.0 322 | 323 | > Stop creating launch script. Instead use fnaify for both 324 | > setup and launch. 325 | > Support for several Zachtronics games. Add libstubborn use to dllmap. 326 | > Symlinking for MonoGame, e.g. NeuroVoider. 327 | > Preferential use of installed FNA.dll over bundled one. 328 | 329 | 2\.2 330 | 331 | > Fix config for mono 6. Add support for libcestub. 332 | 333 | 2\.1 334 | 335 | > Support for additional XNA games. Add MONO\_FORCE\_COMPAT quirk. 336 | 337 | 2\.0 338 | 339 | > Add support for XNA games. 340 | > Introduce interactivity flags 341 | > **-i** | **-y** 342 | > to facilitate adding in needed assemblies/libraries. 343 | 344 | 1\.3 345 | 346 | > Add prompt to download and replace 347 | > *FNA.dll* 348 | > if incompatible version is found. 349 | > Detect steamstubs directory and use Steamworks stubs if present. 350 | 351 | 1\.2 352 | 353 | > FreeBSD portability fixes, account for more special cases (MidBoss, 354 | > Adventures of Shuggy, Atom Zombie Smasher), add directory path to plug 355 | > in additional libraries. 356 | 357 | 1\.1 358 | 359 | > Fix bug selecting .exe by separating input variables. 360 | 361 | 1\.0 362 | 363 | > Initial release. 364 | 365 | # AUTHORS 366 | 367 | Thomas Frohwein <[thfr@openbsd.org](mailto:thfr@openbsd.org)> 368 | Mariusz Zaborski 369 | 370 | OpenBSD 7.2 - September 4, 2022 371 | -------------------------------------------------------------------------------- /fnaify: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ksh 2 | 3 | set -o errexit 4 | set -o pipefail 5 | 6 | FNAIFY_VERSION=3.1 7 | 8 | ######################################################################### 9 | # fnaify # 10 | # ====== # 11 | # # 12 | # Run FNA/XNA games on OpenBSD # 13 | # # 14 | # Copyright (c) 2017-2020 Thomas Frohwein # 15 | # portability fixes by Mariusz Zaborski (oshogbo) # 16 | # # 17 | # FNA is a reimplementation of the Microsoft XNA Game Studio 4.0 # 18 | # Refresh libraries. # 19 | # Thanks to the great work by Ethan Lee (flibitijibibo) games using FNA # 20 | # are highly portable and can even run on OpenBSD. Please refer to # 21 | # https://fna-xna.github.io/ for more information about FNA. # 22 | # # 23 | # License: ISC # 24 | ######################################################################### 25 | 26 | # TODO: 27 | # - fix TODOs 28 | # - fails to detect XNA in Streets of Fury EX because of whitespace; resolved after renaming .exe 29 | # - update the creator for dllmap file; based on fnaify.dllmap.config 30 | # - mention package fnaify-extralibs in documentation 31 | # - add option to add runtime exe_flags to run mode 32 | # - AVNT: find a way to have Steam deactivated for this one in libSteamworksNative.so 33 | # - add flag to create log file (for fnaify, as well as the output from the game) 34 | # - document '--' to end getopts parsing; can make it clear when to pass remaining args to game 35 | # - add check for ffmpeg if needed 36 | 37 | USAGE=" 38 | Usage: 39 | 40 | $(basename "$0") [-i|-y] [-hsv] [-c configfile] [-D depdir] [-d gamedir] [-f frameworkfile | -F frameworkversion] [-m monopath] [userflags] 41 | 42 | -c: specify config file for dllmap 43 | -D: add directory to native library loader 44 | -d: game directory 45 | -F: framework version 46 | -f: framework file 47 | -h: print usage information 48 | -i: interactive mode 49 | -m: add directories to MONO_PATH 50 | -n: skip the library check 51 | -s: force (re-)running setup 52 | -y: non-interactive mode; automatically replies 'yes' to all recommended choices 53 | -V: display version 54 | -v: verbose output 55 | 56 | are optional. These arguments are passed to the game runtime. 57 | " 58 | 59 | depdir="/usr/local/lib:/usr/X11R6/lib" # /usr/X11R6/lib is location of libfreetype.so on OpenBSD 60 | fnadir="/usr/local/share/FNA" 61 | gamedir="$PWD" 62 | interaction=n # y|n|i: yes to all, no to all, interactive 63 | debug= 64 | licenses= 65 | gameconfig= 66 | force_setup=0 67 | nolibcheck=0 68 | frameworkfile= 69 | setup_frameworkfile= 70 | frameworkversion= 71 | setup_frameworkversion= 72 | frameworkmajor= 73 | frameworkminor= 74 | userflags= 75 | monopath="${MONO_PATH}" 76 | netstub_commit=e7d890e0ede0caa9e76ef37af6070344e3ab0abf 77 | newline=' 78 | ' 79 | SAVEIFS=$IFS 80 | exefile= 81 | nexefile=0 # TODO: is nexefile really needed? 82 | my_exe="" 83 | exe_flags="" 84 | exe_env="" 85 | fna_warning=0 86 | nlog_warning=0 87 | set -A needlibarray # array that will hold the names of needed libraries 88 | FNAIFY_DEBUG=false 89 | 90 | if [ -d "/usr/local/lib/steamworks-nosteam" ] ; then 91 | monopath="${monopath}:/usr/local/lib/steamworks-nosteam" 92 | depdir="/usr/local/lib/steamworks-nosteam:$depdir" 93 | fi 94 | if [ -d "$fnadir" ] ; then 95 | monopath="${monopath}:${fnadir}" 96 | fi 97 | if [ -d "/usr/local/share/steamstubs" ]; then 98 | monopath="${monopath}:/usr/local/share/steamstubs" 99 | fi 100 | if [ -d "/usr/local/share/fnaify-libs" ]; then 101 | depdir="/usr/local/share/fnaify-libs:$depdir" 102 | fi 103 | 104 | # array of lib names to ignore for the configuration checking 105 | ignoredarray=" 106 | FarseerPhysics.Portable.xml 107 | libCommunityExpressSW.so 108 | libCSteamworks.so 109 | libGalaxy64.so 110 | libGalaxyCSharpGlue.so 111 | libGalaxy.so 112 | libParisSteam.so 113 | libSkiaSharp.so 114 | libSteamWrapper.so 115 | libXNAFileDialog.so 116 | libXNAWebRenderer.so 117 | libsteam_api.so 118 | libcef.so 119 | libfmod.so 120 | libfmodex.so 121 | libfmodstudio.so 122 | liblua53.so 123 | libmojoshader.so 124 | libtiny_jpeg.so 125 | steamwrapper.so 126 | steam_appid.txt 127 | " 128 | 129 | # array of mono files that need to be removed from the game folder 130 | monofilearray=" 131 | CSteamworks.dll 132 | I18N.CJK.dll 133 | I18N.MidEast.dll 134 | I18N.Other.dll 135 | I18N.Rare.dll 136 | I18N.West.dll 137 | I18N.dll 138 | Microsoft.CSharp.dll 139 | Mono.CSharp.dll 140 | Mono.Posix.dll 141 | Mono.Security.dll 142 | Steam.dll 143 | System.Configuration.dll 144 | System.Configuration.Install.dll 145 | System.Core.dll 146 | System.Data.dll 147 | System.Design.dll 148 | System.Drawing.dll 149 | System.IO.Compression.FileSystem.dll 150 | System.IO.Compression.dll 151 | System.Management.dll 152 | System.Net.dll 153 | System.Numerics.dll 154 | System.Runtime.Serialization.dll 155 | System.Security.dll 156 | System.ServiceModel.dll 157 | System.Transactions.dll 158 | System.Web.Extensions.dll 159 | System.Web.Http.dll 160 | System.Web.Services.dll 161 | System.Web.dll 162 | System.Windows.Forms.dll 163 | System.Xml.Linq.dll 164 | System.Xml.dll 165 | System.dll 166 | WindowsBase.dll 167 | libMonoPosixHelper.so 168 | libMonoPosixHelper.so.x86 169 | libMonoPosixHelper.so.x86_64 170 | libSteamworksNative.so 171 | monoconfig 172 | monomachineconfig 173 | mscorlib.dll 174 | " 175 | 176 | configbasearray=" 177 | BlitNet.dll 178 | CDGEngine.dll 179 | CommunityExpress.dll 180 | FMOD.dll 181 | FNA.dll 182 | GameClasses.dll 183 | MonoGame.Framework.dll 184 | Nuclex.Input.dll 185 | OpenAL-CS.dll 186 | SDL2#.dll 187 | SDL2-CS.dll 188 | " 189 | 190 | debug_echo() 191 | { 192 | [ "$FNAIFY_DEBUG" = "false" ] && return 193 | if [ "${1}" = '-n' ]; then 194 | printf '%b' "$2" 195 | else 196 | printf '%b\n' "$1" 197 | fi 198 | } 199 | 200 | printdash() 201 | { 202 | string= 203 | string="$*" 204 | if [ -z "$string" ]; then 205 | return 206 | fi 207 | printf '%b\n' "$string" 208 | c=1 209 | dashes= 210 | while [ $c -lt ${#string} ] 211 | do 212 | dashes="${dashes}-" 213 | # $((...)) for arithmetic substitution 214 | c=$((c+1)) 215 | done 216 | echo "$dashes" 217 | } 218 | 219 | inarray() # check if $1 is in array $2 220 | { 221 | firstarg="$1" 222 | shift 1 223 | if echo "$*" | grep -q "$firstarg" 224 | then 225 | echo "true" 226 | else 227 | echo "false" 228 | fi 229 | } 230 | 231 | # function to find the latest present library. Return -1 if none found. 232 | # $1 is the basename of the library without the version suffix (e.g. /usr/lib/libc.so) 233 | # it will return the filename of the latest library version (e.g. /usr/lib/libc.so.96.0) 234 | latest_syslib() 235 | { 236 | if [ -z "$1" ] ; then 237 | return 1 238 | fi 239 | find "$(dirname "$1")" -maxdepth 1 -name "$(basename "$1")*" | tail -1 240 | } 241 | 242 | trunklibnam() # truncate library name 243 | { 244 | libnam="$1" 245 | libnam="$(echo "$libnam" | sed -n -E "s/[\.0-9]*$//p")" 246 | echo "$libnam" | sed -E "s/(libSDL2[^-]*)-2\.0(\.so.*)/\1\2/" 247 | } 248 | 249 | validlib() # returns "false" if $1 is in ignoredarray, otherwise "true" 250 | { 251 | libnam="$(trunklibnam "$1")" 252 | if echo \""$ignoredarray"\" | grep -q "$libnam"; then 253 | echo "false" 254 | elif echo \""$libnam"\" | grep -q '\.dll[ \t]*'; then 255 | echo "false" 256 | else 257 | echo "true" 258 | fi 259 | } 260 | 261 | symlink_mg_libs() 262 | { 263 | set -A mg_subdirs x64 x86 264 | debug_echo "\nChecking for MonoGame x64/x86 dir to create symlinks" 265 | 266 | if [ ! -e "$gamedir/x64" ] && [ ! -e "$gamedir/x86" ] ; then 267 | debug_echo "...Couldn't find directories x64 or x86 in $gamedir\n" 268 | else 269 | for d in "${mg_subdirs[@]}" ; do 270 | debug_echo "\nProcessing library directory $gamedir/$d" 271 | for file in $gamedir/$d; do 272 | # sort out libs that need to be ignored 273 | if [ "$(validlib "$file")" = "true" ] 274 | then 275 | debug_echo "\tignored file: $file" 276 | continue 277 | fi 278 | debug_echo "\tfound library file: $file. Replacing with symlink..." 279 | trunk=$(trunklibnam "$file") 280 | rm "$gamedir/$d/$file" 281 | debug_echo -n "\t\tchecking for location of $trunk... " 282 | if [ -n "$(latest_syslib "/usr/local/lib/$trunk")" ] ; then 283 | debug_echo "found in /usr/local/lib!" 284 | trunkpath="/usr/local/lib/$trunk" 285 | elif [ -n "$(latest_syslib "/usr/X11R6/lib/$trunk")" ] ; then 286 | debug_echo "found in /usr/X11R6/lib!" 287 | trunkpath="/usr/X11R6/lib/$trunk" 288 | elif [ -n "$(latest_syslib "/usr/lib/$trunk")" ] ; then 289 | debug_echo "found in /usr/lib!" 290 | trunkpath="/usr/lib/$trunk" 291 | else 292 | debug_echo "NOT FOUND!!" 293 | trunkpath= 294 | printf "\n\t - ERROR: couldn't find system lib for %s\n" "$file" 295 | fi 296 | ln -s "$(latest_syslib "$trunkpath")" "$gamedir/$d/$file" 297 | done 298 | debug_echo "Done with library directory $gamedir/$d" 299 | done 300 | debug_echo "\nCreating libdl.so.2 symlink\n" 301 | [ ! -e "$gamedir/libdl.so.2" ] && \ 302 | ln -s "$(latest_syslib /usr/lib/libc.so)" "$gamedir/libdl.so.2" 303 | fi 304 | } 305 | 306 | selectexe() 307 | { 308 | debug_echo "\nexecutable assembly selection routine" 309 | IFS=" 310 | " 311 | for xfile in $(cd "$gamedir" && find . -maxdepth 1 -type f -iname "*.exe" -exec basename {} \; | sort) 312 | do 313 | if echo "$xfile" | ! grep -q vshost && \ 314 | echo "$xfile" | ! grep -iq config && \ 315 | echo "$xfile" | ! grep -q dotNetFx4 && \ 316 | echo "$xfile" | ! grep -q Updater 317 | then 318 | exefile="$exefile$xfile:" 319 | nexefile=$((nexefile + 1)) 320 | fi 321 | done 322 | IFS=$SAVEIFS 323 | if [ $nexefile -gt 1 ]; then 324 | if [ "$interaction" = "y" ] ; then 325 | # TODO: for now just pick the first .exe. Come up with 326 | # better heuristic 327 | my_exe="$(echo "$exefile" | cut -f 1 -d ':')" 328 | else 329 | i=1 330 | while [ $i -le $nexefile ]; do 331 | echo "$i: $(echo "$exefile" | cut -f $i -d ':')" 332 | i=$((i + 1)) 333 | done 334 | input_exe=0 335 | while [ ${#input_exe} -gt 2 ] \ 336 | || ! echo "$input_exe" | grep -q '[1-9]' \ 337 | || [ $input_exe -gt $((i - 1)) ] 338 | do 339 | echo -n "Enter number of .exe file to run: " 340 | read -r input_exe 341 | done 342 | # NOTE: this only works for up to 9 candidate files 343 | my_exe="$(echo "$exefile" | cut -f "$input_exe" -d ':')" 344 | fi 345 | elif [ $nexefile -eq 1 ]; then 346 | my_exe="$exefile" 347 | else 348 | # TODO: there appear to be games without .exe, like Streets of Rage 4 349 | printf "ERROR: no .exe file found\n\n" 350 | exit 1 351 | fi 352 | my_exe="$(echo "$my_exe" | sed -E "s/[ \t]$//")" # trim trailing whitespace 353 | } 354 | 355 | check_gameconfig() 356 | { 357 | if [ -z "$gameconfig" ] ; then 358 | if [ -f "$HOME/.config/fnaify/fnaify.dllmap.config" ] ; then 359 | gameconfig="$HOME/.config/fnaify/fnaify.dllmap.config" 360 | # check for outdated config file 361 | if [ "$(grep -m 1 "fnaify version $FNAIFY_VERSION" "$gameconfig")" = "" ] ; then 362 | echo "WARNING: $gameconfig appears to be out of date. It is strongly recommended to remove it and re-run $(basename "$0")." 363 | fi 364 | else 365 | if [ -f "$fnadir/FNA.dll.config" ] ; then 366 | gameconfig="$fnadir/FNA.dll.config" 367 | elif [ -f "/usr/local/share/fnaify/fnaify.dllmap.config" ] ; then 368 | gameconfig="/usr/local/share/fnaify/fnaify.dllmap.config" 369 | else # in this case create ~/.config/fnaify/fnaify.dllmap.config 370 | gameconfig="$HOME/.config/fnaify/fnaify.dllmap.config" 371 | debug_echo "creating $gameconfig" 372 | mkdir -p ~/.config/fnaify 373 | cat < "$gameconfig" 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | EOF 695 | fi 696 | fi 697 | fi 698 | } 699 | 700 | libraryname() 701 | { 702 | version="$1" 703 | if [ ! -e "$gamedir/$version" ]; then 704 | debug_echo "Couldn't find library directory $gamedir/$version" 705 | else 706 | debug_echo "\nEntering library directory $gamedir/$version" 707 | for file in "$gamedir"/"$version"/*; do 708 | file="$(basename "$file")" 709 | # sort out libs that need to be ignored 710 | if [ "$(validlib "$file")" = "true" ] 711 | then 712 | debug_echo "\tignored file: $file" 713 | continue 714 | fi 715 | debug_echo -n " found library file: $file" 716 | file=$(trunklibnam "$file") 717 | debug_echo -n " -> $file" 718 | case "$(inarray "$file" "${needlibarray}")" in 719 | "true") 720 | debug_echo " - already in array" 721 | ;; 722 | "false") 723 | needlibarray[$((${#needlibarray[*]} + 1))]="$file" 724 | debug_echo "" 725 | ;; 726 | *) 727 | printf "\n\tERROR: inarray returned with unexpected error\n\n" 728 | exit 1 729 | ;; 730 | esac 731 | done 732 | debug_echo "Done with library directory $gamedir/$version" 733 | fi 734 | } 735 | 736 | # install FNA into gamedir; specify version (e.g. 17.12) as $1 737 | # if XNA bridge should be installed, add "xna_bridge" as $2 738 | install_fna() 739 | { 740 | if [ $# -lt 1 ]; then 741 | echo "ERROR: install_fna called with insufficient arguments" 742 | exit 1 743 | fi 744 | fna_version= 745 | if [ "${1}" = 'latest' ]; then 746 | # get version number of latest release from GitHub API 747 | fna_version=$(ftp -Vo - https://api.github.com/repos/FNA-XNA/FNA/releases/latest \ 748 | | grep -Eo "\"tag_name\"\:\"[0-9\.]*\"" \ 749 | | cut -d\" -f4) 750 | else 751 | fna_version="$1" 752 | fi 753 | printf '\nInstalling FNA %s ...' "${fna_version}\n" 754 | licenses="${licenses}FNA:\t\tMs-PL (https://github.com/FNA-XNA/FNA/blob/master/licenses/LICENSE)${newline}" 755 | lastdir="$PWD" 756 | cd /tmp || exit 1 757 | ftp -V "https://github.com/FNA-XNA/FNA/releases/download/${fna_version}/FNA-$(echo "$fna_version" | tr -d '.').zip" 758 | debug_echo "extracting FNA ${fna_version}" 759 | unzip "FNA-$(echo "$fna_version" | tr -d '.').zip" > /dev/null 760 | if [ $# -gt 1 ] \ 761 | && [ "$2" = "xna_bridge" ] 762 | then 763 | printf '\nInstalling FNA.NetStub for XNA ...\n' 764 | licenses="${licenses}FNA.NetStub:\tMs-PL (https://github.com/FNA-XNA/FNA.NetStub/blob/master/LICENSE)${newline}" 765 | ftp -V https://github.com/FNA-XNA/FNA.NetStub/archive/$netstub_commit.tar.gz 766 | tar zxf $netstub_commit.tar.gz 767 | mv FNA.NetStub-$netstub_commit FNA.NetStub 768 | echo -n "compiling XNA ABI/bridge files. This may take a moment... " 769 | xbuild /p:Configuration=Release FNA/abi/Microsoft.Xna.Framework.sln >> /tmp/fnaify-xbuild.log 770 | echo "done." 771 | cp /tmp/FNA/abi/bin/Release/* "$gamedir/" 772 | else 773 | # Download Vorbisfile-CS to be included in the build 774 | ftp https://raw.githubusercontent.com/flibitijibibo/Vorbisfile-CS/master/Vorbisfile.cs 775 | # add in FNA.Settings.props 776 | cat < FNA/FNA.Settings.props 777 | 778 | 779 | 780 | 781 | 782 | 783 | EOF 784 | echo -n "compiling FNA ${fna_version} with xbuild... " 785 | xbuild /p:Configuration=Release FNA/FNA.sln >> /tmp/fnaify-xbuild.log 786 | echo "done." 787 | echo "Moving FNA.dll to fnaify-backup subdirectory" 788 | mkdir -p "$gamedir/fnaify-backup" 789 | mv "$gamedir/FNA.dll" "$gamedir/fnaify-backup/" 790 | cp /tmp/FNA/bin/Release/FNA.dll "$gamedir" 791 | fi 792 | debug_echo "removing the temporary build directories and returning to previous directory" 793 | rm -rf /tmp/FNA /tmp/FNA.NetStub /tmp/Vorbisfile.cs 794 | cd "$lastdir" || exit 1 795 | } 796 | 797 | check_nlog() 798 | { 799 | if [ -f "$gamedir/NLog.dll" ] ; then 800 | nlogversion=$(monodis --assembly "$gamedir/NLog.dll" | grep "Version" | tr -d '[:alpha:]' | tr -d " " | tr -d :) 801 | nlogmajor=$(echo "$nlogversion" | sed -n -E "s/\..*//p") 802 | nlogminor=$(echo "$nlogversion" | sed -n -E "s/[0-9]+\.([0-9]+)\.[0-9]+\.[0-9]+/\1/p") 803 | debug_echo -n "\tNLog.dll version $nlogversion, " 804 | debug_echo -n "major: $nlogmajor, " 805 | debug_echo "minor: $nlogminor" 806 | if [ "$nlogmajor" -lt 4 ] \ 807 | && [ "$interaction" = "i" ] 808 | then 809 | printf '\nInstall NLog 4.6.5 from www.nuget.org? [y/n] ' 810 | response= 811 | until [ "$response" = "y" ] || [ "$response" = "n" ] 812 | do 813 | read -r response 814 | done 815 | elif [ "$nlogmajor" -lt 4 ] && [ "$interaction" = "y" ] ; then 816 | response="y" 817 | else 818 | response="n" 819 | fi 820 | if [ "$response" = "y" ] ; then 821 | debug_echo "Moving old NLog.dll out of the way" 822 | mkdir -p "$gamedir/fnaify-backup" 823 | mv "$gamedir/NLog.dll" "$gamedir/fnaify-backup/" 824 | lastdir="$PWD" 825 | mkdir /tmp/nlog 826 | cd /tmp/nlog || exit 1 827 | printf '\nInstalling NLog 4.6.5 ...\n' 828 | licenses="${licenses}NLog:\tBSD 3-clause (https://github.com/NLog/NLog/blob/master/LICENSE.txt)${newline}" 829 | ftp -Vo nlog.4.6.5.nupkg https://www.nuget.org/api/v2/package/NLog/4.6.5 830 | unzip nlog.4.6.5.nupkg > /dev/null 831 | cp lib/net45/NLog.dll "$gamedir/" 832 | cd "$lastdir" || exit 1 833 | rm -rf /tmp/nlog 834 | elif [ "$nlogmajor" -lt 4 ] ; then 835 | nlog_warning=1 836 | fi 837 | fi 838 | } 839 | 840 | process_options() 841 | { 842 | while getopts c:Dd:F:f:hil:m:nsVvy o; do 843 | case "$o" in 844 | c) gameconfig="$OPTARG" ;; 845 | D) debug="--debug" ;; 846 | d) gamedir=$(readlink -f "$OPTARG") ;; 847 | f) frameworkfile="$OPTARG" ;; 848 | F) frameworkversion="$OPTARG" ;; 849 | h) echo "$USAGE"; exit 0;; 850 | i) interaction=i ;; 851 | l) depdir="$OPTARG" ;; 852 | m) monopath="$OPTARG" ;; 853 | n) nolibcheck=1 ;; 854 | s) force_setup=1 ;; 855 | V) echo "$FNAIFY_VERSION"; exit 0;; 856 | v) FNAIFY_DEBUG=true ;; 857 | y) interaction=y ;; 858 | --) break ;; 859 | *) ;; 860 | esac 861 | done 862 | debug_echo "options: $*" 863 | debug_echo "OPTIND: $OPTIND" 864 | shift $((OPTIND-1)) 865 | debug_echo "options after shift: $*\n" 866 | userflags=$* 867 | } 868 | 869 | check_mono_binaries() 870 | { 871 | debug_echo "Checking mono and monodis" 872 | if [ -z "$FNAIFY_MONO" ]; then 873 | FNAIFY_MONO="$(which mono 2>/dev/null)" 874 | fi 875 | [ -z "$FNAIFY_MONO" ] && { \ 876 | echo "error finding mono" 877 | exit 1 878 | } 879 | if ! "$FNAIFY_MONO" --version 2>/dev/null >/dev/null 880 | then 881 | echo "error calling mono - aborting... Please make sure that mono is in path or set it in FNAIFY_MONO environment variable!" 882 | exit 1 883 | fi 884 | # check if monodis can be called 885 | if monodis 2>/dev/null 886 | then 887 | echo "error calling monodis - aborting... Please make sure that monodis is in the PATH!" 888 | exit 1 889 | fi 890 | } 891 | 892 | iomap() 893 | { 894 | debug_echo "iomap: checking if symlinks for filename cases need to be created" 895 | for f in $(find "$gamedir" -maxdepth 1 -name "*.exe" -exec basename {} \;); do 896 | case $f in 897 | WagonAdventure.exe ) 898 | ln -sf CRT.xnb Content/FX/Crt.xnb 899 | ;; 900 | "Dead Pixels.exe" ) 901 | ln -sf Sprites Content/sprites 902 | ln -sf Effects Content/Sprites/effects 903 | ln -sf Splash Content/Sprites/splash 904 | ln -sf Items Content/Sprites/InGame/items 905 | ln -sf Grenades Content/Sprites/InGame/grenades 906 | ln -sf Hud Content/Sprites/InGame/hud 907 | ln -sf insideBuildings Content/Sprites/InGame/InsideBuildings 908 | ln -sf Character Content/Sprites/InGame/character 909 | ln -sf City Content/Sprites/InGame/city 910 | ln -sf Traders Content/Sprites/InGame/traders 911 | ln -sf Zombies Content/Sprites/InGame/zombies 912 | ln -sf Objects Content/Sprites/InGame/objects 913 | ln -sf Other Content/Sprites/InGame/other 914 | ln -sf GunShots Content/Sprites/InGame/gunShots 915 | ln -sf Buttons Content/Sprites/buttons 916 | ln -sf Menu Content/Sprites/menu 917 | ln -sf Cursor Content/Sprites/cursor 918 | ln -sf Achievements Content/Sprites/achievements 919 | ln -sf Credits Content/Sprites/credits 920 | ln -sf Font Content/Sprites/font 921 | ln -sf preview Content/Sprites/Preview 922 | ln -sf preview Content/Sprites/Menu/Preview 923 | ln -sf PsxButtons Content/Sprites/buttons/psxButtons 924 | ln -sf Cutscene Content/Sprites/CutScene 925 | ln -sf buildings Content/Sprites/InGame/City/Buildings 926 | ln -sf mainbackground.xnb Content/ConfigSprites/mainBackground.xnb 927 | ln -sf largeCuts.xnb Content/Sprites/effects/largecuts.xnb 928 | ln -sf smallCuts.xnb Content/Sprites/effects/smallcuts.xnb 929 | ln -sf effects Content/Sprites/Effects 930 | ln -sf cuemark.xnb Content/Sprites/effects/cueMark.xnb 931 | ln -sf Static.xnb Content/Sprites/Menu/Preview/static.xnb 932 | ;; 933 | AJ1.exe ) 934 | ln -sf j_rip.xnb Content/AJ1/j_Rip.xnb 935 | ln -sf j_rip.xnb Content/AJ2/j_Rip.xnb 936 | ln -sf Owlturnneo2.xnb Content/AJ1/owlturnneo2.xnb 937 | ln -sf Owlturnneo2.xnb Content/AJ2/owlturnneo2.xnb 938 | ;; 939 | CSTW.exe ) 940 | ln -sf paws_Happy.xnb Content/Portrait/Paws/Paws_Happy.xnb 941 | ;; 942 | ThePit.exe ) 943 | ln -sf UI Content/ui 944 | ln -sf m_security_bot_C_sprites.xnb Content/characters/enemies/security_bot/m_security_bot_c_sprites.xnb 945 | ;; 946 | "Grand Class Melee.exe" ) 947 | ln -sf water.xnb Content/Sounds/Water.xnb 948 | ln -sf grass.xnb Content/Sounds/Grass.xnb 949 | ln -sf move.xnb Content/Sounds/Move.xnb 950 | ln -sf select.xnb Content/Sounds/Select.xnb 951 | ln -sf back.xnb Content/Sounds/Back.xnb 952 | ln -sf squire_base.xnb Content/Textures/Players/Squire_base.xnb 953 | ln -sf squire_greyscale.xnb Content/Textures/Players/Squire_greyscale.xnb 954 | ln -sf militia_base.xnb Content/Textures/Players/Militia_base.xnb 955 | ln -sf militia_greyscale.xnb Content/Textures/Players/Militia_greyscale.xnb 956 | ln -sf apprentice_base.xnb Content/Textures/Players/Apprentice_base.xnb 957 | ln -sf apprentice_greyscale.xnb Content/Textures/Players/Apprentice_greyscale.xnb 958 | ln -sf savant_base.xnb Content/Textures/Players/Savant_base.xnb 959 | ln -sf savant_greyscale.xnb Content/Textures/Players/Savant_greyscale.xnb 960 | ln -sf sword.xnb Content/Textures/Weapons/Sword.xnb 961 | ln -sf arrow.xnb Content/Sounds/Arrow.xnb 962 | ln -sf scorch.xnb Content/Sounds/Scorch.xnb 963 | ln -sf bigspeed.xnb Content/Sounds/Bigspeed.xnb 964 | ln -sf frame_ingame_left_ruin.xnb Content/Textures/Menu/frame_ingame_left_Ruin.xnb 965 | ln -sf frame_ingame_left_mire.xnb Content/Textures/Menu/frame_ingame_left_Mire.xnb 966 | ln -sf frame_ingame_right_ruin.xnb Content/Textures/Menu/frame_ingame_right_Ruin.xnb 967 | ln -sf frame_ingame_left_wood.xnb Content/Textures/Menu/frame_ingame_left_Wood.xnb 968 | ln -sf ruin_leaf.xnb Content/Textures/Terrain/Ruin_leaf.xnb 969 | ln -sf frame_ingame_right_wood.xnb Content/Textures/Menu/frame_ingame_right_Wood.xnb 970 | ln -sf bigblow1.xnb Content/Sounds/Bigblow1.xnb 971 | ln -sf ruin_grassmove.xnb Content/Textures/Terrain/Ruin_grassmove.xnb 972 | ln -sf wood_leaf.xnb Content/Textures/Terrain/Wood_leaf.xnb 973 | ln -sf ruin_watermove.xnb Content/Textures/Terrain/Ruin_watermove.xnb 974 | ln -sf castshort.xnb Content/Sounds/Castshort.xnb 975 | ln -sf frame_ingame_right_mire.xnb Content/Textures/Menu/frame_ingame_right_Mire.xnb 976 | ln -sf frame_ingame_left_dune.xnb Content/Textures/Menu/frame_ingame_left_Dune.xnb 977 | ln -sf sword1.xnb Content/Sounds/Sword1.xnb 978 | ln -sf frame_ingame_right_dune.xnb Content/Textures/Menu/frame_ingame_right_Dune.xnb 979 | ln -sf staff1.xnb Content/Sounds/Staff1.xnb 980 | ;; 981 | "LaserCat.exe" ) 982 | ln -sf audio Content/Audio 983 | ;; 984 | "MountYourFriends.exe" ) 985 | ln -sf menuBg.xnb Content/images/menubg.xnb 986 | ln -sf humanClean.xnb Content/images/humanclean.xnb 987 | ln -sf humanCleanNorm.xnb Content/images/humancleannorm.xnb 988 | ln -sf menuMarker.xnb Content/images/menumarker.xnb 989 | ln -sf stegersaurusLogo.xnb Content/images/backdrops/stegersauruslogo.xnb 990 | ln -sf UIComponents.xnb Content/images/uicomponents.xnb 991 | ln -sf restrictedArea.xnb Content/images/restrictedarea.xnb 992 | ln -sf goatSheet.xnb Content/images/goatsheet.xnb 993 | ln -sf BP3_SSTRIP_64.xnb Content/images/bp3_sstrip_64.xnb 994 | ln -sf BP3_SSTRIP_32.xnb Content/images/bp3_sstrip_32.xnb 995 | ln -sf keySheet.xnb Content/images/keysheet.xnb 996 | ;; 997 | "One Finger Death Punch.exe" ) 998 | ln -sf font2.xnb Content/Font2.xnb 999 | ln -sf font5.xnb Content/Font5.xnb 1000 | ln -sf font6.xnb Content/Font6.xnb 1001 | ;; 1002 | "PhoenixForce.exe" ) 1003 | ln -sf LIfeBar.xnb Content/1.4/Boss/lifeBar.xnb 1004 | ln -sf firewavexml.xml Content/1.4/Player/fireWavexml.xml 1005 | ln -sf firewave.xnb Content/1.4/Player/fireWave.xnb 1006 | ;; 1007 | "Streets of Fury EX.exe" ) 1008 | ln -sf ShockWave.xnb Content/Texture2D/Shockwave.xnb 1009 | ;; 1010 | "Aces Wild.exe" ) 1011 | ln -sf HitSparks Content/Sprites/Hitsparks 1012 | ln -sf preFabs.awx Content/Data/prefabs.awx 1013 | ;; 1014 | "CameraObscura.exe" ) 1015 | ln -sf enemies Content/Enemies 1016 | ln -sf buttons Content/Buttons 1017 | ln -sf ui Content/UI 1018 | ln -sf particle Content/Particle 1019 | ;; 1020 | "DLC.exe" ) 1021 | ln -sf ../../campaigns/dlcquest/texture/awardmentSpriteSheet.xnb Content/base/texture/awardmentSpriteSheet.xnb 1022 | ln -sf ../../campaigns/dlcquest/texture/dlcSpriteSheet.xnb Content/base/texture/dlcSpriteSheet.xnb 1023 | ln -sf ../../campaigns/dlcquest/data/map Content/base/data/map 1024 | ln -sf ../../campaigns/dlcquest/texture/tiles_16x16.xnb Content/base/texture/tiles_16x16.xnb 1025 | ln -sf ../../campaigns/dlcquest/texture/skyNightSpriteSheet.xnb Content/base/texture/skyNightSpriteSheet.xnb 1026 | ln -sf ../../campaigns/dlcquest/texture/backgroundSpriteSheet.xnb Content/base/texture/backgroundSpriteSheet.xnb 1027 | ln -sf ../../campaigns/dlcquest/texture/background2SpriteSheet.xnb Content/base/texture/background2SpriteSheet.xnb 1028 | ln -sf ../../../campaigns/dlcquest/data/npc/shopkeep.xnb Content/base/data/npc/shopkeep.xnb 1029 | ln -sf ../../../campaigns/dlcquest/data/npc/shopkeep2.xnb Content/base/data/npc/shopkeep2.xnb 1030 | ln -sf ../../../campaigns/dlcquest/data/npc/shepherd.xnb Content/base/data/npc/shepherd.xnb 1031 | ln -sf ../../../campaigns/dlcquest/data/npc/random.xnb Content/base/data/npc/random.xnb 1032 | ln -sf ../../../campaigns/dlcquest/data/npc/filler.xnb Content/base/data/npc/filler.xnb 1033 | ln -sf ../../../campaigns/dlcquest/data/npc/blacksmith.xnb Content/base/data/npc/blacksmith.xnb 1034 | ln -sf ../../../campaigns/dlcquest/data/npc/sidequest.xnb Content/base/data/npc/sidequest.xnb 1035 | ln -sf ../../../campaigns/dlcquest/data/npc/troll.xnb Content/base/data/npc/troll.xnb 1036 | ln -sf ../../../campaigns/dlcquest/data/npc/gunsmith.xnb Content/base/data/npc/gunsmith.xnb 1037 | ln -sf ../../../campaigns/dlcquest/data/npc/princess.xnb Content/base/data/npc/princess.xnb 1038 | ln -sf ../../../campaigns/dlcquest/data/npc/horse.xnb Content/base/data/npc/horse.xnb 1039 | ;; 1040 | "EvilQuest.exe" ) 1041 | ln -sf Weapons Content/weapons 1042 | ln -sf DialogWindow.xnb Content/HUD/dialogWindow.xnb 1043 | ln -sf SpellSprites Content/spellSprites 1044 | ln -sf PromptMessageWindow.xnb Content/HUD/promptMessageWindow.xnb 1045 | ln -sf PromptWindow.xnb Content/HUD/promptWindow.xnb 1046 | ln -sf Menu Content/menu 1047 | ln -sf smallCursor.xnb Content/Menu/smallcursor.xnb 1048 | ln -sf ItemIcons.xnb Content/Menu/itemIcons.xnb 1049 | ln -sf SpellIcons.xnb Content/Menu/spellIcons.xnb 1050 | ln -sf SplashSymbol.xnb Content/Menu/splashSymbol.xnb 1051 | ln -sf SplashChaosoftLogo.xnb Content/Menu/splashChaosoftLogo.xnb 1052 | ln -sf SplashGamesText.xnb Content/Menu/splashGamesText.xnb 1053 | ln -sf PrisonGalvis_NoShadow.xnb Content/prisonGalvis_NoShadow.xnb 1054 | ln -sf EnemySprites Content/enemysprites 1055 | ln -sf Galvis_NoShadow.xnb Content/EnemySprites/galvis_noShadow.xnb 1056 | ln -sf DemonGalvis.xnb Content/demonGalvis.xnb 1057 | ln -sf StunnedEffect.xnb Content/SpellSprites/stunnedEffect.xnb 1058 | ln -sf Colorize.xnb Content/colorize.xnb 1059 | ln -sf bossDialogMusic.xnb Content/BossDialogMusic.xnb 1060 | ln -sf Equip.xnb Content/Menu/equip.xnb 1061 | ln -sf MessageWindow.xnb Content/Menu/messageWindow.xnb 1062 | ln -sf Shop.xnb Content/shop.xnb 1063 | ln -sf Title.xnb Content/Menu/title.xnb 1064 | ln -sf TitleNewGame.xnb Content/Menu/titleNewGame.xnb 1065 | ln -sf TitleNewGameActive.xnb Content/Menu/titleNewGameActive.xnb 1066 | ln -sf GalvisTheme.xnb Content/galvisTheme.xnb 1067 | ln -sf FlamesBG.xnb Content/Intro/Screen1/flamesBG.xnb 1068 | ln -sf FlamesFG.xnb Content/Intro/Screen1/flamesFG.xnb 1069 | ln -sf ForegroundMask.xnb Content/Intro/Screen1/foregroundMask.xnb 1070 | ln -sf VillageBGFire.xnb Content/Intro/Screen3/villageBGFire.xnb 1071 | ln -sf VillageFG.xnb Content/Intro/Screen3/villageFG.xnb 1072 | ln -sf VillageFire.xnb Content/Intro/Screen3/villageFire.xnb 1073 | ln -sf Galvis1.xnb Content/Intro/Screen3/galvis1.xnb 1074 | ln -sf Galvis2.xnb Content/Intro/Screen3/galvis2.xnb 1075 | ln -sf Silhouettes.xnb Content/Intro/Screen4/silhouettes.xnb 1076 | ln -sf FullColor.xnb Content/Intro/Screen4/fullcolor.xnb 1077 | ln -sf FlamesBG.xnb Content/Intro/Screen4/flamesBG.xnb 1078 | ln -sf FlamesFG.xnb Content/Intro/Screen4/flamesFG.xnb 1079 | ln -sf ForegroundMask.xnb Content/Intro/Screen4/foregroundMask.xnb 1080 | ln -sf ArrestFG1.xnb Content/Intro/Screen5/arrestFG1.xnb 1081 | ln -sf ArrestFG2.xnb Content/Intro/Screen5/arrestFG2.xnb 1082 | ln -sf ArrestFG3.xnb Content/Intro/Screen5/arrestFG3.xnb 1083 | ln -sf GalvisEndingCloseUpBG1.xnb Content/Intro/Screen9/GalvisEndingCloseupBG1.xnb 1084 | ln -sf ControlsPC.xnb Content/Menu/controlsPC.xnb 1085 | ln -sf amethyst.xnb Content/Amethyst.xnb 1086 | ln -sf BattlefieldIntro.xnb Content/BATTLEFIELDINTRO.xnb 1087 | ln -sf Prison2.xnb Content/PRISON2.xnb 1088 | ln -sf Prison1.xnb Content/PRISON1.xnb 1089 | ln -sf Items.xml Data/items.dat 1090 | ln -sf NPCs.xml Data/NPCS.dat 1091 | ;; 1092 | "HELLYEAH.exe" ) 1093 | ln -sf QuadNoir.xnb Content/QUADNOIR.xnb 1094 | ln -sf QuadBlanc.xnb Content/QUADBLANC.xnb 1095 | ln -sf TRANS_Mask.xnb Content/TRANS_MASK.xnb 1096 | ln -sf Popup Content/GAME/HUD/POPUP 1097 | ln -sf pop_u_trung.xnb Content/GAME/HUD/Popup/POP_U_TRUNG.xnb 1098 | ln -sf popup_cartouche_noir.xnb Content/GAME/HUD/Popup/POPUP_CARTOUCHE_NOIR.xnb 1099 | ln -sf popup_barre_rouges.xnb Content/GAME/HUD/Popup/POPUP_BARRE_ROUGES.xnb 1100 | ln -sf Menu_\(arial\).xnb Content/TITLE/FONTS/MENU_\(ARIAL\).xnb 1101 | ln -sf cursor.xnb Content/PCONLY/CURSORS/CURSOR.xnb 1102 | ln -sf viseur.xnb Content/PCONLY/CURSORS/VISEUR.xnb 1103 | ln -sf Shaders Content/SHADERS 1104 | ln -sf WhiteFlash.xnb Content/Shaders/WHITEFLASH.xnb 1105 | ln -sf VaguePoison.xnb Content/Shaders/VAGUEPOISON.xnb 1106 | ln -sf Black.xnb Content/Shaders/BLACK.xnb 1107 | ln -sf White.xnb Content/Shaders/WHITE.xnb 1108 | ln -sf BloomExtract.xnb Content/Shaders/BLOOMEXTRACT.xnb 1109 | ln -sf BloomCombine.xnb Content/Shaders/BLOOMCOMBINE.xnb 1110 | ln -sf GaussianBlur.xnb Content/Shaders/GAUSSIANBLUR.xnb 1111 | ln -sf Sobel.xnb Content/Shaders/SOBEL.xnb 1112 | ln -sf RadialBlur.xnb Content/Shaders/RADIALBLUR.xnb 1113 | ln -sf VagueFeu.xnb Content/Shaders/VAGUEFEU.xnb 1114 | ln -sf ColorEffects.xnb Content/Shaders/COLOREFFECTS.xnb 1115 | ln -sf Explosion.xnb Content/Shaders/EXPLOSION.xnb 1116 | ln -sf Ripple.xnb Content/Shaders/RIPPLE.xnb 1117 | ln -sf RedFilter.xnb Content/Shaders/REDFILTER.xnb 1118 | ln -sf Distortion.xnb Content/Shaders/DISTORTION.xnb 1119 | ln -sf Lightning.xnb Content/Shaders/LIGHTNING.xnb 1120 | ln -sf LoadingWheel.xnb Content/GAME/LOADING/LOADINGWHEEL.xnb 1121 | ln -sf LOGO_Sega.xnb Content/LOGO/LOGO_SEGA.xnb 1122 | ln -sf LOGO_Arkedo.xnb Content/LOGO/LOGO_ARKEDO.xnb 1123 | ln -sf Sounds Content/GAME/WORLD/SOUNDS 1124 | ln -sf HY_Sounds.xnb Content/GAME/WORLD/Sounds/HY_SOUNDS.xnb 1125 | ln -sf picto_A.xnb Content/GAME/FONTS/PICTO/PICTO_A.xnb 1126 | ln -sf picto_B.xnb Content/GAME/FONTS/PICTO/PICTO_B.xnb 1127 | ln -sf picto_BK.xnb Content/GAME/FONTS/PICTO/PICTO_BK.xnb 1128 | ln -sf picto_LB.xnb Content/GAME/FONTS/PICTO/PICTO_LB.xnb 1129 | ln -sf picto_LS.xnb Content/GAME/FONTS/PICTO/PICTO_LS.xnb 1130 | ln -sf picto_LT.xnb Content/GAME/FONTS/PICTO/PICTO_LT.xnb 1131 | ln -sf picto_PAD.xnb Content/GAME/FONTS/PICTO/PICTO_PAD.xnb 1132 | ln -sf picto_RB.xnb Content/GAME/FONTS/PICTO/PICTO_RB.xnb 1133 | ln -sf picto_RS.xnb Content/GAME/FONTS/PICTO/PICTO_RS.xnb 1134 | ln -sf picto_RT.xnb Content/GAME/FONTS/PICTO/PICTO_RT.xnb 1135 | ln -sf picto_ST.xnb Content/GAME/FONTS/PICTO/PICTO_ST.xnb 1136 | ln -sf picto_X.xnb Content/GAME/FONTS/PICTO/PICTO_X.xnb 1137 | ln -sf picto_Y.xnb Content/GAME/FONTS/PICTO/PICTO_Y.xnb 1138 | ln -sf picto_RS1.xnb Content/GAME/FONTS/PICTO/PICTO_RS1.xnb 1139 | ln -sf picto_RS2.xnb Content/GAME/FONTS/PICTO/PICTO_RS2.xnb 1140 | ln -sf picto_RS3.xnb Content/GAME/FONTS/PICTO/PICTO_RS3.xnb 1141 | ln -sf picto_RS4.xnb Content/GAME/FONTS/PICTO/PICTO_RS4.xnb 1142 | ln -sf picto_360.xnb Content/GAME/FONTS/PICTO/PICTO_360.xnb 1143 | ln -sf saving.xnb Content/LOGO/SAVING.xnb 1144 | ln -sf branchetonpad.xnb Content/PCONLY/MENUS/BRANCHETONPAD.xnb 1145 | ln -sf pckey.xnb Content/PCONLY/MENUS/PCKEY.xnb 1146 | ln -sf mousecenter.xnb Content/PCONLY/MENUS/MOUSECENTER.xnb 1147 | ln -sf mousedefault.xnb Content/PCONLY/MENUS/MOUSEDEFAULT.xnb 1148 | ln -sf mousedirections.xnb Content/PCONLY/MENUS/MOUSEDIRECTIONS.xnb 1149 | ln -sf mouseleftbt.xnb Content/PCONLY/MENUS/MOUSELEFTBT.xnb 1150 | ln -sf mouserightbt.xnb Content/PCONLY/MENUS/MOUSERIGHTBT.xnb 1151 | ln -sf mousewheelup.xnb Content/PCONLY/MENUS/MOUSEWHEELUP.xnb 1152 | ln -sf mousewheeldown.xnb Content/PCONLY/MENUS/MOUSEWHEELDOWN.xnb 1153 | ln -sf ls.xnb Content/PCONLY/MENUS/LS.xnb 1154 | ln -sf ls1.xnb Content/PCONLY/MENUS/LS1.xnb 1155 | ln -sf ls2.xnb Content/PCONLY/MENUS/LS2.xnb 1156 | ln -sf ls360.xnb Content/PCONLY/MENUS/LS360.xnb 1157 | ln -sf rs1.xnb Content/PCONLY/MENUS/RS1.xnb 1158 | ln -sf rs2.xnb Content/PCONLY/MENUS/RS2.xnb 1159 | ln -sf rs3.xnb Content/PCONLY/MENUS/RS3.xnb 1160 | ln -sf rs4.xnb Content/PCONLY/MENUS/RS4.xnb 1161 | ln -sf "INT_Radar_(good_girl).xnb" "Content/GAME/FONTS/INT_RADAR_(GOOD_GIRL).xnb" 1162 | ln -sf "DLG_Name_(trashand).xnb" "Content/GAME/FONTS/DLG_NAME_(TRASHAND).xnb" 1163 | ln -sf Particules Content/TITLE/PARTICULES 1164 | ln -sf boum.xnb Content/TITLE/Particules/BOUM.xnb 1165 | ln -sf flameches.xnb Content/TITLE/Particules/FLAMECHES.xnb 1166 | ln -sf fumee_background_flou.xnb Content/TITLE/Particules/FUMEE_BACKGROUND_FLOU.xnb 1167 | ln -sf fumee_noire.xnb Content/TITLE/Particules/FUMEE_NOIRE.xnb 1168 | ln -sf gaz_multicolor.xnb Content/TITLE/Particules/GAZ_MULTICOLOR.xnb 1169 | ln -sf TITLE_Cartouche.xnb Content/TITLE/TITLE_CARTOUCHE.xnb 1170 | ln -sf TITLE_Subtitle-EN.xnb Content/TITLE/TITLE_SUBTITLE-EN.xnb 1171 | ln -sf TITLE_Logo.xnb Content/TITLE/TITLE_LOGO.xnb 1172 | ln -sf TITLE_FlameScroll.xnb Content/TITLE/TITLE_FLAMESCROLL.xnb 1173 | ln -sf TITLE_LogoMask.xnb Content/TITLE/TITLE_LOGOMASK.xnb 1174 | ln -sf TITLE_Background.xnb Content/TITLE/TITLE_BACKGROUND.xnb 1175 | ln -sf TITLE_Select.xnb Content/TITLE/TITLE_SELECT.xnb 1176 | ;; 1177 | "HonourRuns.exe" ) 1178 | ln -sf Sprites Content/sprites 1179 | ln -sf Textures Content/textures 1180 | ln -sf Levels Content/levels 1181 | ;; 1182 | "POOF.exe" ) 1183 | ln -sf QuadNoir.xnb Content/QUADNOIR.xnb 1184 | ln -sf QuadBlanc.xnb Content/QUADBLANC.xnb 1185 | ln -sf TRANS_Mask.xnb Content/TRANS_MASK.xnb 1186 | ;; 1187 | # beware, SSDD and SSDDXXL have the same named SSGame.exe 1188 | "SSGame.exe" ) 1189 | # SSDDXXL 1190 | ln -s HUD_ShopBackground.xnb Content/textures/menus/HUD_Shopbackground.xnb 1191 | ln -s GLOBAL.xnb Content/levels/global.xnb 1192 | ln -s HUD_challenge_skull.xnb Content/textures/menus/hud_challenge_skull.xnb 1193 | ln -s LEVEL1.xnb Content/levels/level1.xnb 1194 | # SSDD 1195 | ln -s FRONT.xnb Content/levels/front.xnb 1196 | ;; 1197 | "TheFallOfGods2.exe" ) 1198 | ln -sf Data Content/data 1199 | ;; 1200 | "Snails.exe" ) 1201 | ln -s ScreensData.xnb Content/screens/screensdata.xnb 1202 | ln -s footerMessage.xnb Content/fonts/footermessage.xnb 1203 | ln -s MainMenu.xnb Content/screens/mainmenu.xnb 1204 | ln -s UISnailsMenu.xnb Content/screens/controls/uisnailsmenu.xnb 1205 | ln -s UIMainMenuBodyPanel.xnb Content/screens/controls/uimainmenubodypanel.xnb 1206 | ;; 1207 | "WoCGame.exe" ) 1208 | ln -s Arial14.xnb Content/fonts/arial14.xnb 1209 | ;; 1210 | esac 1211 | done 1212 | IFS=$SAVEIFS 1213 | } 1214 | 1215 | xnasetup() 1216 | { 1217 | if [ ! -d "$fnadir" ] ; then 1218 | if [ "$interaction" = "i" ] ; then 1219 | printf '\nInstall FNA files from GitHub to for this XNA application? [y/n] ' 1220 | response= 1221 | until [ "$response" = "y" ] || [ "$response" = "n" ] 1222 | do 1223 | read -r response 1224 | done 1225 | elif [ "$interaction" = "y" ] ; then 1226 | response="y" 1227 | else 1228 | response="n" 1229 | fi 1230 | 1231 | if [ "$response" = "y" ]; then 1232 | install_fna latest xna_bridge 1233 | else 1234 | printf 'Failed to install FNA/XNA files. Try running with -i or -y flag\n' 1235 | exit 1 1236 | fi 1237 | fi 1238 | 1239 | # convert .wma to .ogg and .wmv to .ogv 1240 | # https://gist.github.com/flibitijibibo/c97bc14aab04b1277d8ef5e97fc9aeff 1241 | IFS=" 1242 | " 1243 | # TODO: check for errors on return of these commands 1244 | echo "checking for WMA/WMV files and converting. This may take several minutes..." 1245 | for afile in $(find "$gamedir" -name "*.wma"); do 1246 | echo "converting $afile to OGG" 1247 | ffmpeg -loglevel fatal -i "$afile" -c:a libvorbis -q:a 10 \ 1248 | "$(echo "$afile" | rev | cut -d. -f2-$(($(echo "$afile" \ 1249 | | tr -dc '.' | wc -c) + 1)) | rev).ogg" \ 1250 | || echo "...skipping..." 1251 | done 1252 | for vfile in $(find . -name "*.wmv"); do 1253 | echo "converting $vfile to OGV" 1254 | ffmpeg -loglevel fatal -i "$vfile" -c:v libtheora -q:v 10 -c:a libvorbis \ 1255 | -q:a 10 "$(echo "$vfile" | rev | cut -d. -f2-$(($(echo "$vfile" \ 1256 | | tr -dc '.' | wc -c) + 1)) | rev).ogv" \ 1257 | || echo "...skipping..." 1258 | done 1259 | IFS=$SAVEIFS 1260 | echo " done." 1261 | } 1262 | 1263 | get_setup_frameworkfile() 1264 | { 1265 | if [ -e "$gamedir/FNA.dll" ] ; then 1266 | setup_frameworkfile="$gamedir/FNA.dll" 1267 | elif [ -e "$gamedir/MonoGame.Framework.dll" ] ; then 1268 | setup_frameworkfile="$gamedir/MonoGame.Framework.dll" 1269 | fi 1270 | } 1271 | 1272 | get_frameworkversion() 1273 | { 1274 | if [ -f "$1" ] ; then 1275 | monodis --assembly "$1" | grep -F Version | sed -E 's/Version:[[:blank:]]*//' 1276 | fi 1277 | } 1278 | 1279 | get_frameworkmajor() 1280 | { 1281 | echo "$1" | sed -n -E "s/([0-9]+)\.[0-9\.]+/\1/p" 1282 | } 1283 | 1284 | get_frameworkminor() 1285 | { 1286 | # strip leading zeros 1287 | echo "$1" | sed -n -E "s/[0-9]+\.([0-9]+).*/\1/p" | sed "s/^0*//" 1288 | } 1289 | 1290 | check_eagle_island() 1291 | { 1292 | { [ -f "$gamedir/EagleIsland.exe" ] && \ 1293 | [ "$(basename "$gamedir")" != "Linux" ]; } && \ 1294 | { \ 1295 | debug_echo "correct gamedir for Eagle Island" 1296 | gamedir="${gamedir}/Linux" 1297 | } 1298 | } 1299 | 1300 | run() 1301 | { 1302 | check_eagle_island 1303 | [ -e "$gamedir/.fnaify_ready" ] || { echo "ERROR: setup not completed."; exit 1; } 1304 | check_mono_binaries 1305 | cd "$gamedir" || exit 1 1306 | 1307 | selectexe 1308 | check_gameconfig 1309 | [ -e "$gameconfig" ] || { echo "ERROR: provided gameconfig file not existent: $gameconfig"; exit 1; } 1310 | debug_echo "gameconfig: $gameconfig" 1311 | 1312 | # Quirks 1313 | my_exe="$(echo "$my_exe" | tr -d '\:')" 1314 | case "$my_exe" in 1315 | Blueberry.exe|Shenzhen.exe|ThePit.exe ) 1316 | exe_env="${exe_env}MONO_FORCE_COMPAT=1 " 1317 | ;; 1318 | Hacknet.exe ) 1319 | exe_flags="${exe_flags}-disableweb " 1320 | ;; 1321 | ScourgeBringer.exe ) 1322 | exe_flags="${exe_flags}-noSound " 1323 | ;; 1324 | MidBoss.exe ) 1325 | if [ -e fnaify.dllmap.MidBoss.config ] && 1326 | [ "$(diff -U 0 "$gameconfig" fnaify.dllmap.MidBoss.config | \ 1327 | wc -l)" -eq 5 ] 1328 | then 1329 | debug_echo "fnaify.dllmap.MidBoss.config up to date." 1330 | else 1331 | debug_echo "fnaify.dllmap.MidBoss.config is missing or out of date." 1332 | debug_echo "creating fnaify.dllmap.MidBoss.config from $gameconfig for MidBoss" 1333 | # copy $gameconfig to fnaify.dllmap.MidBoss.config 1334 | cp "$gameconfig" fnaify.dllmap.MidBoss.config 1335 | # edit fnaify.dllmap.MidBoss.config to use libSDL2_image_compact.so 1336 | sed -Ei 's/libSDL2_image\.so/libSDL2_image_compact.so/g' \ 1337 | fnaify.dllmap.MidBoss.config 1338 | # redefine gameconfig to fnaify.dllmap.MidBoss.config 1339 | gameconfig=fnaify.dllmap.MidBoss.config 1340 | fi 1341 | ;; 1342 | SSGame.exe ) 1343 | mkdir -p ~/.local/share/SSDD 1344 | ;; 1345 | esac 1346 | 1347 | for f in $configbasearray; do 1348 | [ -e "$f" ] && { \ 1349 | debug_echo "existing symlink target: ${f}.config -> $(readlink "${f}.config")" 1350 | gameconfigsymlink="${gameconfigsymlink}${f}.config " 1351 | [ "$gameconfig" = "$(readlink "${f}.config")" ] \ 1352 | || ln -sf "$gameconfig" "${f}.config" 1353 | } 1354 | done 1355 | gameconfigsymlink="${gameconfigsymlink}${my_exe}.config " 1356 | [ "$gameconfig" = "$(readlink "${my_exe}.config")" ] || \ 1357 | ln -sf "$gameconfig" "${my_exe}.config" 1358 | 1359 | # format all relevant command variables 1360 | depdir="$(echo "$depdir" | sed -E 's/:$//')" 1361 | monopath="$(echo "$monopath" | sed -E 's/:$//' | sed -E 's/^://')" 1362 | 1363 | ######################################### 1364 | # Heuristic for frameworkfile selection # 1365 | ######################################### 1366 | 1367 | # Scenario: user-specified framework file (-f) 1368 | if [ -n "$frameworkfile" ] ; then 1369 | debug_echo "using user-supplied frameworkfile: $frameworkfile" 1370 | 1371 | # Scenario: MonoGame.Framework.dll 1372 | elif [ -f "$gamedir/MonoGame.Framework.dll" ] ; then 1373 | frameworkfile="$gamedir/MonoGame.Framework.dll" 1374 | 1375 | # Scenario: user-specified framework version (-F) 1376 | elif [ -n "$frameworkversion" ] ; then 1377 | # check fnadir and gamedir for fitting version 1378 | if [ -f "$fnadir/FNA.dll" ] ; then 1379 | file_fwv="$(get_frameworkversion "$fnadir/FNA.dll")" 1380 | if [ "$(get_frameworkmajor "$file_fwv").$(get_frameworkminor "$file_fwv")" = "$(get_frameworkmajor "$frameworkversion").$(get_frameworkminor "$frameworkversion")" ] ; then 1381 | frameworkfile="$fnadir/FNA.dll" 1382 | fi 1383 | fi 1384 | if [ -z "$frameworkfile" ] && [ -f "$gamedir/FNA.dll" ] ; then 1385 | file_fwv="$(get_frameworkversion "$gamedir/FNA.dll")" 1386 | if [ "$(get_frameworkmajor "$file_fwv").$(get_frameworkminor "$file_fwv")" = "$(get_frameworkmajor "$frameworkversion").$(get_frameworkminor "$frameworkversion")" ] ; then 1387 | frameworkfile="$gamedir/FNA.dll" 1388 | fi 1389 | fi 1390 | if [ -z "$frameworkfile" ] ; then 1391 | install_fna "$frameworkversion" 1392 | frameworkfile="$gamedir/FNA.dll" 1393 | fi 1394 | 1395 | # Scenario: no frameworkfile in gamedir 1396 | elif [ ! -f "$gamedir/FNA.dll" ] ; then 1397 | if [ -e "$gamedir/.fnaify_needfna" ] ; then 1398 | # this occurs if fnaify uses system framework file 1399 | if [ -f "$fnadir/FNA.dll" ] ; then 1400 | frameworkfile="$fnadir/FNA.dll" 1401 | else 1402 | echo "ERROR: frameworkfile needed, but not found. Try re-installing?" 1403 | exit 1404 | fi 1405 | else 1406 | debug_echo "game without framework file" 1407 | fi 1408 | 1409 | # Scenario: FNA.dll in fnadir 1410 | elif [ -f "$fnadir/FNA.dll" ] ; then 1411 | # existence of $gamedir/FNA.dll is implied by above elif [ ! -f $gamedir/FNA.dll ] 1412 | debug_echo "by default, move FNA.dll out of gamedir if present in fnadir" 1413 | mkdir -p "$gamedir/fnaify-backup" 1414 | mv "$gamedir/FNA.dll" "$gamedir/fnaify-backup/" 1415 | debug_echo "touch .fnaify_needfna to make it clear framework file is needed" 1416 | touch "$gamedir/.fnaify_needfna" 1417 | frameworkfile="$fnadir/FNA.dll" 1418 | 1419 | # Scenario: FNA.dll in gamedir - suboptimal for compatibility since mojoshader updates 1420 | else 1421 | # existence of $gamedir/FNA.dll implied by above 1422 | frameworkfile="$gamedir/FNA.dll" 1423 | fi 1424 | 1425 | if [ -z "$frameworkversion" ] ; then 1426 | frameworkversion="$(get_frameworkversion "$frameworkfile")" 1427 | fi 1428 | 1429 | datasize=$(( $(ulimit -d) / 1024 )) 1430 | 1431 | echo 1432 | printdash "fnaify runtime configuration" 1433 | echo "fnaify Version: $FNAIFY_VERSION" 1434 | echo "Game Directory: $PWD" # PWD as cd'd into $gamedir happened above 1435 | echo "Mono Binary: $FNAIFY_MONO" 1436 | echo "Mono Path: $monopath" 1437 | echo "Main Assembly: $my_exe" 1438 | echo "Native Library Directories: $depdir" 1439 | echo "Framework File: $frameworkfile" 1440 | echo "Framework File Version: $frameworkversion" 1441 | echo "Symlinks to Config: $gameconfigsymlink" 1442 | echo "Config File: $gameconfig" 1443 | echo "Other Runtime Environment: $exe_env" 1444 | echo "Runtime Flags: $exe_flags $userflags" 1445 | echo "Datasize Limit: ${datasize} M" 1446 | echo 1447 | 1448 | [ $datasize -lt 2048 ] && { \ 1449 | echo "AT LEAST 2G are recommended for most games. See ksh(1) for ulimit command documentation" 1450 | echo 1451 | } 1452 | 1453 | # check if broken symlinks exist in the game directory, e.g. libdl.so.2 1454 | IFS=' 1455 | ' 1456 | for l in $(find . -type l); do 1457 | IFS=$SAVEIFS 1458 | if [ ! -e "$l" ] ; then 1459 | newl="$(latest_syslib "$(trunklibnam "$(readlink "$l")")")" 1460 | if [ -z "$newl" ] ; then 1461 | echo "ERROR - broken symlink: $l. Expect trouble." 1462 | else 1463 | ln -fs "$newl" "$l" 1464 | fi 1465 | fi 1466 | done 1467 | 1468 | debug_echo "env LD_LIBRARY_PATH=\"$depdir\" MONO_PATH=\"$monopath\" $exe_env \"$FNAIFY_MONO\" $debug \"$my_exe\" $exe_flags $userflags" 1469 | debug_echo "" 1470 | env LD_LIBRARY_PATH="$depdir" MONO_PATH="$monopath" $exe_env "$FNAIFY_MONO" $debug "$my_exe" $exe_flags $userflags 1471 | 1472 | exit 0 1473 | } 1474 | 1475 | setup() 1476 | { 1477 | echo "Performing setup (mode: $interaction) ..." 1478 | check_mono_binaries 1479 | check_eagle_island 1480 | 1481 | cd "$gamedir" || exit 1 1482 | debug_echo "gamedir: $PWD" # cd'd into direct above 1483 | 1484 | debug_echo "Setting up the framework files" 1485 | get_setup_frameworkfile 1486 | if [ -z "$setup_frameworkfile" ]; then 1487 | debug_echo "... no framework file found. Checking other options..." 1488 | else 1489 | debug_echo " framework file: $setup_frameworkfile" 1490 | setup_frameworkversion="$(get_frameworkversion "$setup_frameworkfile")" 1491 | debug_echo " framework version: $setup_frameworkversion" 1492 | fi 1493 | 1494 | if [ -z "$setup_frameworkfile" ] ; then 1495 | # games without framework files: 1496 | # Atom Zombie Smasher, Eliza, Molek-Syntez, Exapunks, Opus Magnum (Lightning.exe), 1497 | # Shenzhen I/O, SpaceChem (64bit and fullscreen update from 2020-07-15), Streets of Fury EX 1498 | # Last Call BBS 1499 | if [ -f "$gamedir/AtomZombieSmasher.exe" ] ; then 1500 | if ls $(echo "$depdir" | tr -s ':' ' ') | grep -q "libatomstb\.so" 1501 | then 1502 | debug_echo "\tfound libatomstb library in a library directory" 1503 | else 1504 | # add libatomstb to needlibarray 1505 | if [ "$(inarray libatomstb.so "$needlibarray")" = "false" ] 1506 | then 1507 | needlibarray[$((${#needlibarray[*]} + 1))]="$libatomstb.so" 1508 | debug_echo "\tlibatomstb.so added to array" 1509 | fi 1510 | fi 1511 | elif [ -f "$gamedir/Eliza.exe" ] \ 1512 | || [ -f "$gamedir/MOLEK-SYNTEZ.exe" ] \ 1513 | || [ -f "$gamedir/EXAPUNKS.exe" ] \ 1514 | || [ -f "$gamedir/Lightning.exe" ] \ 1515 | || [ -f "$gamedir/Shenzhen.exe" ] \ 1516 | || [ -f "$gamedir/SpaceChem.exe" ] \ 1517 | || [ -f "$gamedir/Hammerwatch.exe" ] \ 1518 | || [ -f "$gamedir/SOR4.exe" ] \ 1519 | || [ -f "$gamedir/MobiusFront83.exe" ] \ 1520 | || [ -f "$gamedir/Proteus.exe" ] \ 1521 | || [ -f "$gamedir/LastCallBBS.exe" ] 1522 | then 1523 | debug_echo "\nCompatible game without XNA/FNA framework file found." 1524 | debug_echo "Creating \$HOME/Desktop directory which is needed for Zachtronics games" 1525 | mkdir -p "$HOME/Desktop" 1526 | else 1527 | found_xna=0 1528 | IFS=' 1529 | ' 1530 | for f in $(find . -maxdepth 1 \( -iname "*.exe" -o -iname "*.dll" \) -exec file {} \; \ 1531 | | grep -F "Mono/.Net assembly"); do 1532 | f="$(echo "$f" | cut -d : -f 1)" 1533 | debug_echo "Checking $f for XNA" 1534 | if ! $(monodis --assemblyref "$f" 2>&1 | grep -Fqim1 "Microsoft.Xna.Framework") 1535 | then 1536 | found_xna=1 1537 | break 1538 | fi 1539 | done 1540 | IFS=$SAVEIFS 1541 | if [ $found_xna -gt 0 ]; then 1542 | debug_echo "Found XNA reference" 1543 | xnasetup 1544 | else 1545 | echo "No FNA, MonoGame or XNA reference found" 1546 | exit 1 1547 | fi 1548 | fi 1549 | fi 1550 | 1551 | if [ "$setup_frameworkfile" = "FNA.dll" ] && { [ "$frameworkmajor" -lt 16 ] || { [ "$frameworkmajor" -eq 16 ] && [ "$frameworkminor" -lt 5 ];};} 1552 | then 1553 | fna_warning=1 1554 | fi 1555 | 1556 | check_nlog 1557 | 1558 | set -A configfilesarray # empty the array 1559 | nconfigfilesarray=0 # TODO: is this really needed? 1560 | debug_echo "Identifying config files..." 1561 | IFS=" 1562 | " 1563 | if [ -f "$gamedir"/*.config ]; then 1564 | for cfile in "$gamedir"/*.config; do 1565 | cfile="$(basename "$cfile")" 1566 | debug_echo " found config file: $cfile" 1567 | configfilesarray[$((${#configfilesarray[*]} + 1))]="$cfile" 1568 | nconfigfilesarray=$((nconfigfilesarray + 1)) 1569 | done 1570 | fi 1571 | IFS=$SAVEIFS 1572 | debug_echo "Done identifying config files.\n" 1573 | 1574 | if [ $nolibcheck -eq 1 ] ; then 1575 | debug_echo "skipping library checks" 1576 | else 1577 | # identify required libraries in .config files and lib{,64} directories 1578 | # TODO: filenames not whitespace-safe (but should not be used in such files anyway) 1579 | printdash "$(debug_echo "Identifying libraries required by the game...")" 1580 | 1581 | #for MidBoss, add SDL2_image_compact to needlib 1582 | [ -f "$gamedir/MidBoss*" ] && \ 1583 | needlibarray[$((${#needlibarray[*]} + 1))]="libSDL2_image_compact.so" 1584 | 1585 | libraryname "lib64" 1586 | libraryname "lib" 1587 | libraryname "x64" 1588 | libraryname "x86" 1589 | 1590 | debug_echo "\nChecking for library references in config files..." 1591 | if [ $nconfigfilesarray -lt 1 ]; then 1592 | debug_echo "...No config files found." 1593 | else 1594 | cfile="" 1595 | IFS=" 1596 | " 1597 | for cfile in "${configfilesarray[@]}"; do 1598 | IFS=$SAVEIFS 1599 | debug_echo "\t$cfile" 1600 | linuxlines=$(grep "os\=\"linux" "$gamedir/$cfile") \ 1601 | || debug_echo "no os=linux entries in $cfile" 1602 | for libstring in $(echo "$linuxlines" | sed -n -E "s/.*target=\"([^\"]+).*/\1/p"); do 1603 | # Fix where library name includes directory information 1604 | libstring=$(echo "$libstring" | sed -E 's/^.\///') 1605 | # remove directories at the start of lib name 1606 | libstring=$(echo "$libstring" | sed -E 's/^.*\///') 1607 | debug_echo -n "\t\tFound library string: $libstring" 1608 | # sort out libs that need to be ignored 1609 | if [ "$(validlib "$libstring")" = "false" ] 1610 | then 1611 | debug_echo " - ignored" 1612 | continue 1613 | fi 1614 | libstring=$(trunklibnam "$libstring") 1615 | debug_echo -n " -> $libstring" 1616 | # add to libstring to needlibarray if not in there yet 1617 | case "$(inarray "$libstring" "$needlibarray")" in 1618 | "true") 1619 | debug_echo " - already in array" 1620 | ;; 1621 | "false") 1622 | needlibarray[$((${#needlibarray[*]} + 1))]="$libstring" 1623 | debug_echo " - added to array" 1624 | ;; 1625 | *) 1626 | printf '\n\t - ERROR: inarray returned with unexpected error\n\n' 1627 | exit 1 1628 | ;; 1629 | esac 1630 | done 1631 | done 1632 | debug_echo "Done with identifying libraries in config files" 1633 | fi 1634 | debug_echo "Done with identification of needed libraries." 1635 | fi 1636 | 1637 | debug_echo -n "\nChecking if libpng filename needs fixing..." 1638 | i=1 1639 | while [ "$i" -le "${#needlibarray[@]}" ]; do 1640 | needlibarray[i]="$(echo "${needlibarray[i]}" | sed -E "s/(libpng)..(\.so.*)/\1\2/")" 1641 | i=$((i + 1)) 1642 | done 1643 | debug_echo " done.\n" 1644 | 1645 | # Check if the libraries are available on the system (/usr/local/lib). 1646 | # If not, break and inform user which libraries need to be installed. 1647 | 1648 | debug_echo "Checking installed libraries... " 1649 | # missinglibs[*] accumulates missing library names to inform user 1650 | missinglibs="" 1651 | for needlib in ${needlibarray}; do 1652 | if ls $(echo "$depdir" | tr -s ':' ' ') | grep -q "$needlib" 1653 | then 1654 | IFS=$SAVEIFS 1655 | debug_echo "\tfound library for: $needlib" 1656 | else 1657 | IFS=$SAVEIFS 1658 | debug_echo "\tNot found: $needlib" 1659 | missinglibs="$missinglibs$needlib " 1660 | fi 1661 | done 1662 | debug_echo "done.\n" 1663 | 1664 | if [ -n "${missinglibs}" ]; then 1665 | printf '\nCould not find the following libraries:\n\n%b\n' "${missinglibs}" 1666 | exit 1 1667 | fi 1668 | 1669 | # identify all .config files that do dllmap and move out of the way 1670 | debug_echo 'moving .config files with dllmap out of the way' 1671 | if [ ! -d "$gamedir/fnaify-backup" ] ; then 1672 | mkdir -p "$gamedir/fnaify-backup" 1673 | fi 1674 | IFS=" 1675 | " 1676 | for config_file in "${configfilesarray[@]}"; do 1677 | IFS=$SAVEIFS 1678 | if [ ! -h "$config_file" ] && grep -q "dllmap" "$config_file"; then 1679 | mv "$config_file" "$gamedir/fnaify-backup/" 1680 | fi 1681 | done 1682 | 1683 | debug_echo "Moving some bundled dll files into fnaify-backup subfolder... " 1684 | for file in $monofilearray; do 1685 | if [ -e "$gamedir/$file" ]; then 1686 | debug_echo "\tFound bundled mono file: $file" 1687 | mkdir -p "$gamedir/fnaify-backup" 1688 | mv "$gamedir/$file" "$gamedir/fnaify-backup/" 1689 | fi 1690 | done 1691 | debug_echo " done." 1692 | 1693 | # if necessary, replace FNA.dll 1694 | fna_replace="" 1695 | lastdir="" 1696 | if [ $fna_warning -eq 1 ]; then 1697 | if [ "$interaction" = "i" ] ; then 1698 | printf '\nWARNING: version of FNA.dll potentially incompatble!\n' 1699 | echo "Fetch FNA 17.12 from GitHub, compile, and replace bundled FNA.dll?" 1700 | echo "FNA is distributed under Microsoft Public License. The license" 1701 | echo "can be viewed here:" 1702 | echo "https://github.com/FNA-XNA/FNA/blob/master/licenses/LICENSE" 1703 | echo -n "Proceed with replacing FNA with version 17.12 (recommended)? [y/n] " 1704 | until [ "$fna_replace" = "y" ] || [ "$fna_replace" = "n" ]; do 1705 | read -r fna_replace 1706 | done 1707 | elif [ "$interaction" = "y" ] ; then 1708 | fna_replace="y" 1709 | else 1710 | fna_replace="n" 1711 | fi 1712 | 1713 | if [ "$fna_replace" = "y" ]; then 1714 | install_fna 17.12 1715 | fna_warning=0 1716 | fi 1717 | fi 1718 | 1719 | symlink_mg_libs 1720 | iomap 1721 | 1722 | if [ -n "${licenses}" ]; then 1723 | printf 'Installed modules are under the following license(s):\n\n' 1724 | echo "${licenses}" 1725 | fi 1726 | if [ $fna_warning -eq 1 ]; then 1727 | printf '\nWARNING: version of FNA.dll potentially incompatible!\n' 1728 | printf "If the game doesn't run, try running 'fnaify -i' (or 'fnaify -y').\n\n" 1729 | fi 1730 | if [ $nlog_warning -eq 1 ]; then 1731 | printf '\nWARNING: version of NLog.dll potentially incompatible!\n' 1732 | printf "If the game doesn't run, try running 'fnaify -i' (or 'fnaify -y').\n\n" 1733 | fi 1734 | 1735 | touch .fnaify_ready 1736 | } 1737 | 1738 | ### END OF VARIABLES AND FUNCTIONS ### 1739 | 1740 | ################### 1741 | ### MAIN ### 1742 | ################### 1743 | 1744 | process_options "$@" 1745 | if [ $force_setup -gt 0 ] 1746 | then 1747 | setup 1748 | run 1749 | else 1750 | [ ! -e "$gamedir/.fnaify_ready" ] && setup 1751 | run 1752 | fi 1753 | -------------------------------------------------------------------------------- /fnaify.1: -------------------------------------------------------------------------------- 1 | .Dd $Mdocdate: January 19 2023 $ 2 | .Dt FNAIFY 1 3 | .Os 4 | .Sh NAME 5 | .Nm fnaify 6 | .Nd run FNA/XNA games on OpenBSD 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl i | y 10 | .Op Fl hnsv 11 | .Op Fl c Ar configfile 12 | .Op Fl D Ar depdir 13 | .Op Fl d Ar gamedir 14 | .Op Fl f Ar frameworkfile | Fl F Ar frameworkversion 15 | .Op Fl m Ar monopath 16 | .Op Ar userflags 17 | .Sh DESCRIPTION 18 | .Nm 19 | runs games based on the FNA engine with OpenBSD-native 20 | libraries and its 21 | .Xr mono 1 22 | runtime. 23 | .Pp 24 | As of version 2.0, 25 | .Nm 26 | has been extended to attempt configuring XNA games as well. 27 | .Nm 28 | can be run in 3 basic modes regarding the addition of missing libraries: 29 | restrictive 30 | .Po 31 | default 32 | .Pc 33 | , interactive, and permissive. 34 | .Pp 35 | As of version 3.0, 36 | .Nm 37 | unifies both setup and launch of supported games in one command. 38 | .Pp 39 | All games require additional libraries from ports, like SDL2. Some of 40 | them can be found in the fnaify-extralibs package, like libatomstb or 41 | libfmod_SDL. 42 | .Pp 43 | The arguments are as follows: 44 | .Bl -tag -width Ds 45 | .It Fl i | y 46 | The mode determines how 47 | .Nm 48 | handles situations where compatibility problems are identified that can 49 | be addressed with drop-in DLL replacements, or where an option needs to 50 | be selected. 51 | With 52 | .Fl i , 53 | .Nm 54 | runs in interactive mode, meaning the user will be prompted in every 55 | case. 56 | With 57 | .Fl y , 58 | .Nm 59 | runs in permissive mode 60 | .Po 61 | .Fl y 62 | for 63 | .Dq yes 64 | to all 65 | .Pc . 66 | This means that any suggested drop-in DLLs will be installed, 67 | and if different options are possible (like picking among several .exe 68 | files for the launch script), the first one will be selected 69 | automatically. 70 | If neither 71 | .Fl i 72 | nor 73 | .Fl y 74 | is specified, 75 | .Nm 76 | runs in restrictive mode, that is no drop-in DLLs will be installed. 77 | .It Fl c Ar configfile 78 | Optional. Use 79 | .Ar configfile 80 | for the configuration of 81 | .Xr mono 1 . 82 | This sets up dllmap/dllentry settings to use the correct libraries. See 83 | .Xr mono-config 5 84 | for details. If this option is omitted, 85 | .Nm 86 | looks first for 87 | .Pa ~/.config/fnaify/fnaify.dllmap.config 88 | and then for 89 | .Pa /usr/local/share/fnaify/fnaify.dllmap.config . 90 | If neither one is found, 91 | .Nm 92 | creates 93 | .Pa ~/.config/fnaify/fnaify.dllmap.config 94 | with default settings. 95 | .It Fl D Ar depdir 96 | Add 97 | .Ar depdir 98 | to the directories to search for native library dependencies. 99 | A directory specified this way will be searched 100 | .Em before 101 | the default locations 102 | .Pq Pa /usr/local/lib No etc. . 103 | .It Fl d Ar gamedir 104 | Path to the game's directory 105 | .Pq defaults to the current working directory . 106 | .It Fl F Ar frameworkversion 107 | Choose a specific framework version to use. 108 | .It Fl f Ar frameworkfile 109 | Framework file to use. Typically 110 | .Pa FNA.dll 111 | or 112 | .Pa MonoGame.Framework.dll . 113 | By default will automatically identify the bundled file in the 114 | game's directory. 115 | .It Fl h 116 | Prints help text. 117 | .It Fl m Ar monopath 118 | Add 119 | .Ar monopath 120 | to the directories the 121 | .Xr mono 1 122 | runtime will search for DLLs. 123 | .It Fl n 124 | Skip checks for library dependencies. 125 | .It Fl s 126 | Force (re-)running setup. 127 | .It Fl V 128 | Display version of 129 | .Nm . 130 | .It Fl v 131 | Verbose mode. 132 | .It Ar userflags 133 | Optional. 134 | Flags that are passed to the game as arguments 135 | .El 136 | .Sh SUPPORTED GAMES 137 | Games marked with [!] may have errors or other significant limitations. 138 | .Pp 139 | .Bl -item -compact 140 | .It 141 | The Adventures of Shuggy 142 | .It 143 | Akane the Kunoichi 144 | .It 145 | Amazing Princess Sarah [!] 146 | .It 147 | Apotheon 148 | .It 149 | Apple Jack 1&2 150 | .It 151 | Atom Zombie Smasher 152 | .It 153 | A Virus Named TOM [!] 154 | .It 155 | Before the Echo [!] 156 | .It 157 | Bird Assassin 158 | .It 159 | Bleed 160 | .It 161 | Bleed 2 162 | .It 163 | Blossom Tales II: The Minotaur Prince 164 | .It 165 | Breath of Death VII 166 | .It 167 | Brushwood Buddies 168 | .It 169 | Camera Obscura 170 | .It 171 | Capsized 172 | .It 173 | Capsule Force 174 | .It 175 | Celeste (no audio) 176 | .It 177 | Chaos Heart [!] 178 | .It 179 | Charlie Murder 180 | .It 181 | Chasm 182 | .It 183 | CometStriker 184 | .It 185 | Cryptark 186 | .It 187 | Crystal Project 188 | .It 189 | Cthulhu Saves the World 190 | .It 191 | Curse of the Crescent Isle DX 192 | .It 193 | Dad Quest 194 | .It 195 | Dead Pixels [!] 196 | .It 197 | Dead Pixels II (Early Access) 198 | .It 199 | Diehard Dungeon 200 | .It 201 | The Dishwasher: Vampire Smile 202 | .It 203 | Draw a Stickman: EPIC 204 | .It 205 | Dust: An Elysian Tail 206 | .It 207 | DwarfCorp 208 | .It 209 | Eagle Island [!] 210 | .It 211 | Eliza 212 | .It 213 | Escape Goat 214 | .It 215 | Escape Goat 2 216 | .It 217 | EXAPUNKS 218 | .It 219 | FEZ [!] 220 | .It 221 | Fist Puncher 222 | .It 223 | Flinthook 224 | .It 225 | Flotilla 226 | .It 227 | Gateways 228 | .It 229 | Glitchangels 230 | .It 231 | Grand Class Melee 2 [!] 232 | .It 233 | Growing Pains 234 | .It 235 | HackNet 236 | .It 237 | Hidden in Plain Sight 238 | .It 239 | Hive 240 | .It 241 | Hyphen 242 | .It 243 | Jon Shafer's At the Gates 244 | .It 245 | LaserCat 246 | .It 247 | Last Call BBS 248 | .It 249 | Little Racers STREET 250 | .It 251 | Mercenary Kings 252 | .It 253 | Miasma: Citizens of Free Thought 254 | .It 255 | Miasma 2: Freedom Uprising [!] 256 | .It 257 | MidBoss 258 | .It 259 | Mobius Front '83 [!] 260 | .It 261 | Molek-Syntez 262 | .It 263 | Mount Your Friends 264 | .It 265 | NeuroVoider [!] 266 | .It 267 | Ninja Warrior 268 | .It 269 | One Finger Death Punch 270 | .It 271 | Opus Magnum 272 | .It 273 | Overdriven Reloaded 274 | .It 275 | Owlboy 276 | .It 277 | Paladin 278 | .It 279 | Penny Arcade's On the Rain-Slick Precipice of Darkness 3 280 | .It 281 | Penny Arcade's On the Rain-Slick Precipice of Darkness 4 282 | .It 283 | Phoenix Force [!] 284 | .It 285 | PlanetFriend 286 | .It 287 | Press X to Not Die 288 | .It 289 | Rex Rocket 290 | .It 291 | Rogue Legacy 292 | .It 293 | Ruggnar 294 | .It 295 | Salt and Sanctuary 296 | .It 297 | Session Seven 298 | .It 299 | Shenzhen I/O 300 | .It 301 | Shipwreck [!] 302 | .It 303 | Signs of Life 304 | .It 305 | Skulls of the Shogun 306 | .It 307 | Soulcaster 1 & 2 308 | .It 309 | SpaceChem 310 | .It 311 | SpeedRunners 312 | .It 313 | Stardew Valley 314 | .It 315 | Steel Assault 316 | .It 317 | Sumico 318 | .It 319 | Super Amazing Wagon Adventure 320 | .It 321 | Super Bernie World 322 | .It 323 | Super Blood Hockey 324 | .It 325 | Super Rad Raygun 326 | .It 327 | Sword of the Stars: The Pit [!] 328 | .It 329 | Terraria 330 | .It 331 | Timespinner 332 | .It 333 | TowerFall: Ascension 334 | .It 335 | Ultra Hat Dimension 336 | .It 337 | Unexplored 338 | .It 339 | Unholy Heights 340 | .It 341 | The Useful Dead 342 | .It 343 | Weapon of Choice [!] 344 | .It 345 | Wizorb [!] 346 | .It 347 | Wyv and Keep 348 | .El 349 | .Sh FILES 350 | .Bl -tag -width Ds 351 | .It Pa /usr/local/share/fnaify/fnaify.dllmap.config 352 | Default configuration file to map DLLs to native libraries. 353 | .It Pa ~/.config/fnaify/fnaify.dllmap.config 354 | User directory configuration file. Takes precedence if it exists. 355 | Make sure to keep it up-to-date! 356 | .El 357 | .Sh EXIT STATUS 358 | .Nm 359 | returns 1 if an error occurred, otherwise 0. 360 | .Sh EXAMPLES 361 | Run in permissive mode, suitable to set up most supported games 362 | automatically. 363 | .Pp 364 | .Dl $ fnaify -y -d path/to/game/directory 365 | .Pp 366 | Run in interactive mode. 367 | .Nm 368 | will prompt the user if any additional DLLs are recommended, or if a 369 | file needs to be selected for the launch script. 370 | .Pp 371 | .Dl $ fnaify -i 372 | .Sh SEE ALSO 373 | .Xr mono 1 , 374 | .Xr mono-config 5 375 | .Sh HISTORY 376 | The 377 | .Nm 378 | utility was originally created in December 2017 by 379 | .An Thomas Frohwein Aq Mt thfr@openbsd.org . 380 | .Sh RELEASE HISTORY 381 | .Bl -tag -width Ds 382 | .It 3.1 383 | Stop removing Steamworks.NET.dll. Instead, rely on other lower level 384 | native libraries (CSteamworks, libsteam_api). Add flag 385 | .Fl n 386 | to skip library checks. 387 | .It 3.0 388 | Stop creating launch script. Instead use fnaify for both 389 | setup and launch. 390 | Support for several Zachtronics games. Add libstubborn use to dllmap. 391 | Symlinking for MonoGame, e.g. NeuroVoider. 392 | Preferential use of installed FNA.dll over bundled one. 393 | .It 2.2 394 | Fix config for mono 6. Add support for libcestub. 395 | .It 2.1 396 | Support for additional XNA games. Add MONO_FORCE_COMPAT quirk. 397 | .It 2.0 398 | Add support for XNA games. 399 | Introduce interactivity flags 400 | .Fl i | y 401 | to facilitate adding in needed assemblies/libraries. 402 | .It 1.3 403 | Add prompt to download and replace 404 | .Pa FNA.dll 405 | if incompatible version is found. 406 | Detect steamstubs directory and use Steamworks stubs if present. 407 | .It 1.2 408 | FreeBSD portability fixes, account for more special cases (MidBoss, 409 | Adventures of Shuggy, Atom Zombie Smasher), add directory path to plug 410 | in additional libraries. 411 | .It 1.1 412 | Fix bug selecting .exe by separating input variables. 413 | .It 1.0 414 | Initial release. 415 | .El 416 | .Sh AUTHORS 417 | .An -nosplit 418 | .An Thomas Frohwein Aq Mt thfr@openbsd.org 419 | .An Mariusz Zaborski 420 | -------------------------------------------------------------------------------- /fnaify.dllmap.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | --------------------------------------------------------------------------------