Initial re-upload

This commit is contained in:
Hazel 2024-08-28 23:39:19 -04:00
commit 570f9247c2
12 changed files with 907 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/monitor_by_id
*.pyc

66
0005731108.py Normal file
View File

@ -0,0 +1,66 @@
""" Game fix for IIDX (UID:0005731108)
"""
# Protonfix for games supporting Windows 8 prefix
# This protonfix expects prefix shared between multiple titles
# Explicitely set overrides for all dlls fetched here even when not using them
# pylint: disable=C0103
import os
from protonfixes import util
def main():
# Generic environment (may be overwritten by subpatch)
util.protontricks("win8")
util.protontricks("sound=alsa")
# Apply optional patches (without bloating protonfixes)
patches = (os.getenv("PROTON_STYLE_PATCH") or "").strip(":")
try:
for patch in patches.split(":") if len(patches) else []:
globals()[f"iidx_{patch}"]()
except KeyError as err:
print(f"gamefix: no patch available for {err}")
def iidx_30():
# probably qpro etc., shader compilation fails for D3DXAssembleShader() - crash with missing callback Direct3DShaderValidatorCreate()
util.protontricks("d3dcompiler_43")
util.protontricks("d3dx9_43")
# this exact override needed for subscreen to be created
util.set_environment("WINEDLLOVERRIDES", "d3dcompiler_43=n,b")
def iidx_29():
# probably qpro etc., shader compilation fails for D3DXAssembleShader() - crash with missing callback Direct3DShaderValidatorCreate()
util.protontricks("d3dcompiler_43")
util.protontricks("d3dx9_43")
# this exact override needed for subscreen to be created
util.set_environment("WINEDLLOVERRIDES", "d3dcompiler_43=n,b")
def iidx_28():
# probably qpro etc., shader compilation fails for D3DXAssembleShader() - crash with missing callback Direct3DShaderValidatorCreate()
util.protontricks("d3dcompiler_43")
util.protontricks("d3dx9_43")
# this exact override needed for subscreen to be created
util.set_environment("WINEDLLOVERRIDES", "d3dcompiler_43=n,b")
def iidx_27():
# crash at 0x180176996, shader compilation fails for D3DXAssembleShader() - crash with missing callback Direct3DShaderValidatorCreate()
util.protontricks("d3dcompiler_43")
util.protontricks("d3dx9_43")
# this exact override needed for subscreen to be created
util.set_environment("WINEDLLOVERRIDES", "d3dcompiler_43=n,b")
def iidx_26():
# explicit to keep constant behaviour with other games (iidx27)
util.set_environment("WINEDLLOVERRIDES", "d3dcompiler_43,d3dx9_43=b,n")
def iidx_25():
# explicit to keep constant behaviour with other games (iidx27)
util.set_environment("WINEDLLOVERRIDES", "d3dcompiler_43,d3dx9_43=b,n")
def tests():
# Most dlls that may or may not be required
util.set_environment("WINEDLLOVERRIDES", "quartz,devenum,dmime,dmsynth,dmloader,dmusic,dsound,dsdmo,msdmo,bmsound-wine,d3dx9_41,d3dx9d_41,d3dx9_43,d3dcompiler_43=n,b")
pass

10
README.md Normal file
View File

@ -0,0 +1,10 @@
# Preface
This repo may seem erratic with no documentation whatsoever.
This is because resources listed here are part of a bigger private repository.
You don't have to use anything from this repo to get games running as these are just there to make process feel more seamless.
That being said part of a guide listed at pages may be harder to follow without any system integration whatsoever, therefore this repository exists, providing the minimal wrappers setup that should work with guide provided.
If it doesn't, create a new issue here, as some wrappers here may be outdated.

20
array_format_to_hex.py Executable file
View File

@ -0,0 +1,20 @@
#!/usr/bin/env python3
# Transform array visually to display 16 elements per line
import sys
import pyperclip
if len(sys.argv) < 2:
exit(1)
stin = pyperclip.paste() if sys.argv[1] == "clip" else sys.argv[1]
asarr = [x.strip() for x in stin.strip().split(",")]
output = ""
for i in range(0, len(asarr), 16):
output += ", ".join(map(str, asarr[i : i + 16])) + ",\n"
output = output.rstrip("\n").rstrip(",")
if sys.argv[1] == "clip":
stin = pyperclip.copy(output)
else:
print(output)

21
bytepatch_intern_to_mon.py Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env python3
# Translates internal documentation patch notations into js format expected by BemaniPatcher
import sys
import pyperclip
if len(sys.argv) < 2:
exit(1)
stin = pyperclip.paste() if sys.argv[1] == "clip" else sys.argv[1]
[*rest, addr, on] = stin.split(":")
[off, on, *rest] = on.split("->")
off = ", ".join([f"0x{x}" for x in off.strip().split(" ")])
on = ", ".join([f"0x{x}" for x in on.strip().split(" ")])
addr = addr.strip()
output = f"{{ offset: {addr}, off: [{off}], on: [{on}] }},"
if sys.argv[1] == "clip":
stin = pyperclip.copy(output)
else:
print(output)

361
ep_bm2dxnix Executable file
View File

@ -0,0 +1,361 @@
#!/bin/bash
# Dump directory expects dir structure like this Beatmania IIDX 26/contents;Beatmania IIDX 26/devel;
## Constant ##
_C_scriptDir="$(dirname -- "$(realpath -- "$0")")"
_C_scriptName="$(basename -- "$(realpath -- "$0")")"
# These constants are config overridable, but it is not recommended to do so (ex. hooks may not work)
_C_dll_override="bm2dx.dll"
_C_lightning_model="--iidxtdj"
_C_rtname="proton-ge-8.16"
_C_pfxname="u573_bm2dx_w8"
# Audio native ASIO -iidxsounddevice is 27+ only
_C_audio_asio1=(-iidxasio ASIO4ALL -iidxsounddevice asio)
_C_audio_asio2=(-iidxasio FlexASIO -iidxsounddevice asio)
_C_audio_asio3=(-iidxasio WineASIO -iidxsounddevice asio)
# Audio native(dsound,24-)/wasapi(25+)
_C_audio_native=(-audiohookdisable)
_C_audio_wasapi=(-iidxsounddevice wasapi)
# Audio spice dummy routing (25+ only, uses wasapi exclusive internally, which gets routed to specific audiobackend)
_C_audio_dummy_asio=(-iidxsounddevice wasapi -audiodummy -audiobackend asio -asiodriverid 0)
_C_audio_dummy_waveout=(-iidxsounddevice wasapi -audiodummy -audiobackend waveout)
_C_audio_dummy_none=(-iidxsounddevice wasapi -audiodummy -audiobackend none)
_C_audio_dummy_pipewire=(-iidxsounddevice wasapi -audiodummy -audiobackend pipewire)
# Network spice builtin endpoint
_C_net_dummy_maint=(-eamaint 1 -ea)
_C_net_dummy_local=(-ea)
## Core ##
_G_root="$_C_scriptDir/../.steam/root"
_G_ep=("$_C_scriptDir/ep_protonnix")
_G_exec=""
_G_args=()
_G_style=""
_G_dumps=""
_G_debug=0
## Game config ##
_G_video="stable"
_G_display=0
_G_refresh_rate=0
_G_fsr=-1
_G_url=""
_G_pcbid=""
_G_hooks=()
_G_devel=()
print_help() {
cat <<EOF
ep_nix:ver:bm2dx
Usage: ${_C_scriptName} [EXiV] [opt-args]
Available arguments:
EXiV style (numeric, required)
--cfg launch config tool (spicecfg)
--dbg launch debug environment (--dbg2 if no value provided, available steps through OR blitting 1: spice, 2: x64dbg, 4: wine, 8: style reserved flag)
--root steam library root directory location override (this is where prefixes/runtimes are saved)
--dumps game dumps root directory location override (assuming steam library if not provided)
--exec run anything inside prefix (allows for running any application aside, you may provide arguments after --)
-- arguments past this are passed to executable instead of defaults (read spice etc.)
-h
--help show help
Examples:
${_C_scriptName} 26 --root /mnt/steamhdd --cfg (launches /mnt/steamhdd/steamapps/common/Beatmania IIDX 26/contents/spicecfg.exe)
${_C_scriptName} 26 (launches $_G_root/steamapps/common/Beatmania IIDX 26/contents/spice64.exe)
${_C_scriptName} 26 --exec /tmp/server.exe -- -p 1108 (runs /tmp/server.exe -p 1108 in IIDX26's environment)
${_C_scriptName} 26 --dbg\$((4 | 1)) (launches second example with only additional wine and spice debug steps)
EOF
}
abort() {
echo "[EXIT] Aborting due to failure at ${FUNCNAME[1]}($1)"
exit 1
}
arg_parse() {
while [ ! -z ${1+x} ]; do
case "$1" in
--help | -h)
shift
print_help
exit 0
;;
--exec)
shift
_G_exec="$1"
shift
;;
--cfg)
: ${_G_exec:="spicecfg.exe"}
shift
;;
--dbg*)
_G_debug="${1:5}"
[ -n "$_G_debug" ] || _G_debug=2
shift
;;
--root)
shift
: ${_G_root:="${1%/}"}
shift
;;
--dumps)
shift
: ${_G_dumps:="${1%/}"}
shift
;;
--)
shift
_G_args+=("${@}")
;;
"")
shift
;;
*)
[ -z "${1##*[!0-9]*}" ] || _G_style="$1"
[ -n "$_G_style" ] || {
echo "Unknown option: $1"
exit 2
}
shift
;;
esac
done
}
cfg_parse() {
# Optional config
cfgjson="$(jq -c "." "$_G_dumps/Beatmania IIDX ${_G_style}/contents/prop/linux.json" 2>/dev/null || echo {})"
# Video
_G_video="$(jq -cr ".video.profile // \"$_G_video\"" <<<"$cfgjson")"
_G_display="$(jq -cr ".video.display // \"$_G_display\"" <<<"$cfgjson")"
_G_refresh_rate="$(jq -cr ".video.refresh_rate // \"$_G_refresh_rate\"" <<<"$cfgjson")"
_G_fsr="$(jq -cr ".video.fsr // \"$_G_fsr\"" <<<"$cfgjson")"
# Network
_G_url="$(jq -cr ".network.url // \"$_G_url\"" <<<"$cfgjson")"
_G_pcbid="$(jq -cr ".network.pcbid // \"$_G_pcbid\"" <<<"$cfgjson")"
# Extra
while read -r entry; do _G_hooks+=("$entry"); done < <(jq -cr '.extra.hooks // [] | .[]' <<<"$cfgjson")
while read -r entry; do _G_devel+=("$entry"); done < <(jq -cr '.extra.devel // [] | .[]' <<<"$cfgjson")
[ "$(jq -cr ".extra.lightning_support" <<<"$cfgjson")" == "false" ] && _C_lightning_model=""
_C_game_module="$(jq -cr ".extra.dll_override // \"$_C_game_module\"" <<<"$cfgjson")"
_C_rtname="$(jq -cr ".extra.rt_override // \"$_C_rtname\"" <<<"$cfgjson")"
_C_pfxname="$(jq -cr ".extra.pfx_override // \"$_C_pfxname\"" <<<"$cfgjson")"
}
monitor_by_id() {
if [ ! $(command -v ./monitor_by_id) ]; then
gcc "$_C_scriptDir/monitor_by_id.c" -o "$_C_scriptDir/monitor_by_id" -lX11 -lXrandr || return
fi
"$_C_scriptDir/monitor_by_id" $1
}
args_iidx22() {
# dummy audio unsupported, fullscreen working fine
_G_args+=("${_C_audio_native[@]}")
[ "$_G_video" != "stable" ] || _G_args+=(-graphics-force-single-adapter)
[ "$_G_url" != "dummy" ] || _G_args+=("${_C_net_dummy_local[@]}")
}
args_iidx30() {
# pipewire supported, fullscreen partially? working subscreen
_G_args+=("${_C_audio_dummy_pipewire[@]}" "${_C_lightning_model[@]}" -nolegacy -touchemuforce)
[ "$_G_video" != "stable" ] || _G_args+=(-graphics-force-single-adapter)
[ "$_G_url" != "dummy" ] || _G_args+=("${_C_net_dummy_maint[@]}")
}
args_iidx29() {
# pipewire supported, fullscreen working subscreen
_G_args+=("${_C_audio_dummy_pipewire[@]}" "${_C_lightning_model[@]}" -nolegacy -touchemuforce)
[ "$_G_video" != "stable" ] || _G_args+=(-graphics-force-single-adapter)
[ "$_G_url" != "dummy" ] || _G_args+=("${_C_net_dummy_maint[@]}")
}
args_iidx28() {
if ((_G_debug & 8)); then
# Workaround for audio initializing for ALSA driver (not recommended)
#export PULSE_LATENCY_MSEC=10
export PIPEWIRE_LATENCY=411/44100
export FIX_RATE=44100
export FIX_CHANNELS="[ FL FR ]"
export FIX_FORMAT="S16LE"
rate=$(pw-metadata -n settings 0 clock.rate)
rate="${rate#*value:\'}"
rate="${rate%%\'*}"
pw-metadata -n settings 0 clock.force-rate 44100
#pw-metadata -n settings 0 clock.force-quantum 441
nohup bash -c "sleep 30; pw-metadata -n settings 0 clock.force-rate $rate; sleep 1; pw-metadata -n settings 0 clock.force-rate --delete;" >/dev/null 2>&1 &
# Results in desync prone audio with alsa, static with pulse
_G_args+=("${_C_audio_wasapi[@]}" "${_C_audio_native[@]}" "${_C_lightning_model[@]}")
else
# pipewire supported, fullscreen working subscreen
_G_args+=("${_C_audio_dummy_pipewire[@]}" "${_C_lightning_model[@]}" -nolegacy -touchemuforce)
[ "$_G_video" != "stable" ] || _G_args+=(-graphics-force-single-adapter)
[ "$_G_url" != "dummy" ] || _G_args+=("${_C_net_dummy_maint[@]}")
fi
}
args_iidx27() {
# pipewire supported, fullscreen working subscreen
_G_args+=("${_C_audio_dummy_pipewire[@]}" "${_C_lightning_model[@]}" -nolegacy -touchemuforce)
[ "$_G_video" != "stable" ] || _G_args+=(-graphics-force-single-adapter)
[ "$_G_url" != "dummy" ] || _G_args+=("${_C_net_dummy_maint[@]}")
}
args_iidx26() {
# pipewire supported, fullscreen breaks on window unfocus
_G_args+=("${_C_audio_dummy_pipewire[@]}")
[ "$_G_video" != "stable" ] || _G_args+=(-w)
[ "$_G_url" != "dummy" ] || _G_args+=("${_C_net_dummy_maint[@]}")
}
args_iidx25() {
# pipewire supported, fullscreen breaks on window unfocus
_G_args+=("${_C_audio_dummy_pipewire[@]}")
[ "$_G_video" != "stable" ] || _G_args+=(-w)
[ "$_G_url" != "dummy" ] || _G_args+=("${_C_net_dummy_local[@]}")
}
gen_args() {
# Skip for override (--) mode
[ "${#_G_args[@]}" -eq 0 ] || {
_G_ep+=(--args "${_G_args[*]}")
return 0
}
# Basic
_G_args+=(-io -iidx -modules modules "$_C_dll_override")
# Style
if [[ $(type -t "args_iidx${_G_style}") == function ]]; then
"args_iidx${_G_style}"
else
_G_args+=("${_C_net_dummy[@]}" "${_C_audio_native[@]}")
fi
# Video
_G_args+=(-monitor $_G_display)
[ "$_G_refresh_rate" -gt 0 ] && _G_args+=(-graphics-force-refresh $_G_refresh_rate)
if [ "$_G_video" = "force_window" ]; then
_G_args+=(-w)
elif [ "$_G_video" = "force_fullscreen" ]; then
_G_args+=(-graphics-force-single-adapter)
fi
# Network
[ -n "$_G_url" ] && [ "$_G_url" != "dummy" ] && _G_args+=(-url "$_G_url")
[ -n "$_G_pcbid" ] && _G_args+=(-p "$_G_pcbid")
# Hooks
for hook in "${_G_hooks[@]}"; do _G_args+=(-k "$hook"); done
# Devel
((_G_debug & 1)) && _G_args+=(${_G_devel[@]})
if ((_G_debug & 2)); then
# _REV: could write line directly into db/*.cmdline instead
echo "[INFO] x64dbg session argument recommendation: '${_G_args[*]} -w'"
else
_G_ep+=(--args "${_G_args[*]}")
fi
}
gen_base() {
# Core setup
styledir="$_G_dumps/Beatmania IIDX ${_G_style}"
patchid="0005731108"
if [ "$_G_style" -lt "25" ]; then
arch=32
else
arch=64
fi
# Proton setup
[ -n "$LD_LIBRARY_PATH" ] && LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:"
[ -n "$WINEDLLPATH" ] && LD_LIBRARY_PATH="${WINEDLLPATH}:"
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}${styledir}/contents/modules"
WINEDLLPATH="${WINEDLLPATH}${styledir}/contents/modules"
export WINEDLLPATH
export LD_LIBRARY_PATH
if ((_G_debug & 4)); then
: ${PROTON_LOG_DIR:="$styledir/contents"}
: ${PROTON_LOG:=1}
: ${WINEDEBUG:="+loaddll,+module"}
export WINEDEBUG
export PROTON_LOG
export PROTON_LOG_DIR
echo "[INFO] Proton log file: '$PROTON_LOG_DIR/steam-${patchid}.log'"
fi
export PROTON_STYLE_PATCH="$PROTON_STYLE_PATCH:$_G_style"
# Video fixes (AMD FSR, NVidia VSync)
WINE_FULLSCREEN_FSR=0
[ -z ${__GL_SYNC_DISPLAY_DEVICE+x} ] && __GL_SYNC_DISPLAY_DEVICE="$(monitor_by_id $_G_display)"
if [ "$_G_fsr" -ge 0 ]; then
WINE_FULLSCREEN_FSR=1
export WINE_FULLSCREEN_FSR_STRENGTH=$_G_fsr
if [ "$_G_style" -ge "30" ]; then
export WINE_FULLSCREEN_FSR_CUSTOM_MODE=1920x1080
elif [ "$_G_style" -ge "20" ]; then
export WINE_FULLSCREEN_FSR_CUSTOM_MODE=1280x720
else
export WINE_FULLSCREEN_FSR_CUSTOM_MODE=640x480
fi
fi
export WINE_FULLSCREEN_FSR
export __GL_SYNC_DISPLAY_DEVICE
# Debug/normal environment generation
if ((_G_debug & 2)); then
styledir="$styledir/devel/debug/x64dbg/x${arch}"
[ -n "$_G_exec" ] || _G_exec="x${arch}dbg.exe"
else
styledir="$styledir/contents"
[ -n "$_G_exec" ] || if [ "$arch" -eq "32" ]; then _G_exec="spice.exe"; else _G_exec="spice${arch}.exe"; fi
fi
# Apply environment
cd "$styledir" || abort "INVALID PATH"
_G_ep+=(--exec "$_G_exec" --uniqueid "$patchid" --runtime "$_G_root/steamapps/common/$_C_rtname" --prefix "$_G_root/steamapps/compatdata/$_C_pfxname" --steam-dir "$_G_root")
}
sanity_check() {
# IIDX
[ -n "$_G_style" ] || abort "INVALID STYLE"
[ -n "$_G_dumps" ] || _G_dumps="$_G_root/steamapps/common"
[ -d "$_G_dumps" ] || abort "INVALID PATH"
# Proton
[ -d "$_G_root/steamapps/common" ] || abort "INVALID PATH"
[ -d "$_G_root/steamapps/compatdata" ] || abort "INVALID PATH"
# Manual features warnings
[ -z ${__GL_SYNC_DISPLAY_DEVICE+x} ] || echo "[WARN] User envar override detected, if game runs at wrong framerates, try unsetting __GL_SYNC_DISPLAY_DEVICE"
# Test only
echo "_G_display: $_G_display"
echo "_G_refresh_rate: $_G_refresh_rate"
echo "_G_fsr: $_G_fsr"
echo "_G_url: $_G_url"
echo "_G_pcbid: $_G_pcbid"
echo "_G_hooks[${#_G_hooks[@]}]: ${_G_hooks[*]}"
echo "_G_devel[${#_G_devel[@]}]: ${_G_devel[*]}"
}
# Set-up environment
arg_parse "${@}"
cfg_parse "${@}"
sanity_check
# command generation
gen_base
gen_args
#abort "__GL_SYNC_DISPLAY_DEVICE=$__GL_SYNC_DISPLAY_DEVICE ${_G_ep[*]}"
exec "${_G_ep[@]}"

283
ep_protonnix Executable file
View File

@ -0,0 +1,283 @@
#!/usr/bin/env bash
# Minified version
_C_scriptName="$(basename -- "$(realpath -- "$0")")"
_C_scriptDir="$(dirname -- "$(realpath -- "$0")")"
_C_rootDir="$(dirname -- "$_C_scriptDir")"
_G_runtime=""
_G_prefix=""
_G_exec=""
_G_args=""
_G_root=""
_G_steamlib=("$HOME/.local/share/Steam")
_G_runmode=()
print_help() {
cat <<EOF
ep_nix:ver:proton
Usage: ${_C_scriptName} [EXiV] [opt-args]
Available arguments:
--runtime path to proton runtime dir root
--prefix path to proton compatdata appid dir root (proton specific wine prefix)
--exec windows binary entry point path (for advanced uses look below)
--args args to provide exec binary (this input is not sanitized and follows escape rules of shell so to pass "val with space" use --args "-arg \"arg with space\"")
--root windows game root (if not set uses working directory)
--uniqueid provide to enable fixes for specific AppID (must be numeric, overrides detected AppID if any, for custom id use 0 padded 10 digit ID ex. custom 21 0000000021 to evade SteamID clashes)
--steam-dir provide each additional steam library roots (with valid libraryfolder.vdf in root)
--async enable simultaneous execution inside the same prefix (uses run instead waitforexitandrun)
--info-hud enable information overlay (provided through mangohud)
--local-only disable internet access
--srpt enable steam remote play together through spoofing the game, needs appid of game chosen as dummy (installed and configured to use helper_steamct as compatibility tool)
-h
--help show help
--exec advanced usage (by value):
eg:// protocol to trigger epic games store simplification wrapper (via legendary)
eg://<APP-ID> APP-ID as used internally by legendary (obtainable through list, App name entry)
eg://by-title/<MATCH-STRING>
MATCH-STRING used to find first matched APP-ID for this title
st:// protocol to trigger steam store simplification wrapper (directly launching games)
EOF
}
arg_parse() {
#echo $PROTON_NO_D3D11
echo "$@"
while [ ! -z ${1+x} ]; do
case "$1" in
--help | -h)
shift
print_help
exit 0
;;
--runtime)
shift
: ${_G_runtime:="${1%/}"}
shift
;;
--steam-dir)
shift
_G_steamlib+=("${1%/}")
shift
;;
--prefix)
shift
: ${_G_prefix:="${1%/}"}
shift
;;
--exec)
shift
: ${_G_exec:="${1%/}"}
if [[ "${_G_exec}" == "eg://"* ]]; then
_G_exec="${_G_exec:5}"
_G_runmode+=('__exec_eg')
fi
shift
;;
--args)
shift
: ${_G_args:="${1}"}
shift
;;
--root)
shift
: ${_G_root:="${1%/}"}
shift
;;
--uniqueid)
shift
[ -z "${1##*[!0-9]*}" ] || export STEAM_COMPAT_APP_ID="$1"
shift
;;
--async)
_G_runmode+=('__async')
shift
;;
--srpt)
_G_runmode+=('__srpt')
shift
shift
;;
--info-hud)
shift
_G_runmode+=('__mango')
;;
--local-only)
shift
_G_runmode+=('__local')
;;
--no-debug)
shift
_G_runmode+=('__silent')
;;
--dry-run)
shift
_G_runmode+=('__dry')
;;
"")
shift
;;
*)
echo "Unknown option: $1"
exit 2
shift
;;
esac
done
}
# Finds path where steamapp has been installed (first occurence)
find_steamapp() {
for el in "${_G_steamlib[@]}"; do
elParse="$el/steamapps/common/$1"
if [ -d "$elParse" ]; then
printf "$elParse"
fi
done
}
setup_legendary() {
# Adjust exec line to represent Epic Games app name based on protocol extension
if [[ "${_G_exec}" == "by-title/"* ]]; then
_G_exec="${_G_exec:9}"
_G_exec="$(/opt/Heroic/resources/app.asar.unpacked/build/bin/linux/legendary list | grep -m 1 -i -- "${_G_exec}" | grep -Po '^.*?\K(?<=App name: ).*?(?= | Version)')"
fi
# Adjust execution to use legendary wrappers
prefix="$prefix /opt/Heroic/resources/app.asar.unpacked/build/bin/linux/legendary launch $_G_exec --no-wine --wrapper \"" # add --dry-run before --no-wine to test
_G_exec=""
suffix="\" $suffix"
}
setup_srpt() {
routeappid="0"
args=()
while [ ! -z ${1+x} ]; do
case "$1" in
--srpt)
shift
[ -z "${1##*[!0-9]*}" ] || routeappid="$1"
[ "$routeappid" -ne "0" ] || routeappid="1860860"
shift
;;
*)
args+=("$1")
shift
;;
esac
done
#echo steam -applaunch "$routeappid" ep_protonnix --cd "$(pwd)" "${args[@]}"
exec steam -applaunch "$routeappid" ep_protonnix --cd "$(pwd)" "${args[@]}"
exit 0
}
# Disable network access
setup_network_block() {
# no systemd (gamemode fails dbus connection, since permissions)
if pidof systemd; then
prefix="systemd-run --scope -p IPAddressDeny=any ${prefix}"
else
prefix="unshare -r -n ${prefix}"
fi
#print_log INFO "Disabling network access"
}
# Setup steam variables
setup_environment() {
# Steam
if [ -n "$STEAM_COMPAT_MOUNTS" ]; then STEAM_COMPAT_MOUNTS="$STEAM_COMPAT_MOUNTS:"; fi # preserve preset additional mounts if any
export STEAM_COMPAT_MOUNTS="${STEAM_COMPAT_MOUNTS}$(find_steamapp "Steamworks Shared"):$_G_runtime:$(find_steamapp "SteamLinuxRuntime_soldier"):$(find_steamapp "Proton EasyAntiCheat Runtime")"
[ -z "${STEAM_COMPAT_APP_ID}" ] && export STEAM_COMPAT_APP_ID="${_G_prefix##*/}" # truncate to string after last occurence of /
[ -z "${STEAM_COMPAT_APP_ID##*[!0-9]*}" ] && export STEAM_COMPAT_APP_ID=0 # set to null if not numeric
export SteamAppId="$STEAM_COMPAT_APP_ID"
export SteamGameId="$STEAM_COMPAT_APP_ID"
export STEAM_COMPAT_INSTALL_PATH="$(realpath -- "$PWD")"
export STEAM_COMPAT_DATA_PATH="$_G_prefix"
export STEAM_COMPAT_SHADER_PATH="${_G_steamlib[${#_G_steamlib[@]} - 1]}/steamapps/shadercache/${_G_prefix##*/}" # ..../steam/steamapps/shadercache/739630
export STEAM_COMPAT_CLIENT_INSTALL_PATH="$HOME/.local/share/Steam/"
export STEAM_COMPAT_TOOL_PATHS="$_G_runtime:$(find_steamapp "SteamLinuxRuntime_soldier")" #:$(find_steamapp "Proton EasyAntiCheat Runtime")"
# Proton
: ${DXVK_STATE_CACHE:=1}
export DXVK_STATE_CACHE
: ${DXVK_ASYNC:=1}
unset DXVK_ASYNC # removed as of GE-Proton7-45 (superseeded by in-drivers extension? VK_EXT_graphics_pipeline_library)
#export RADV_PERFTEST=gpl # VK_EXT_graphics_pipeline_library support for AMD(RADV), for NVIDIA enabled in drivers since 515.49.10 without flag
: ${VKD3D_CONFIG:=no_upload_hvv}
export VKD3D_CONFIG
# Wine (usually preconfigured by proton)
: ${WINEFSYNC:=1}
export WINEFSYNC
# Epic Games Store
if [[ "${_G_runmode[*]}" =~ "__exec_eg" ]]; then
setup_legendary
fi
}
# Set-up environment
arg_parse "${@}"
# Set-up other
if [ -z "$_G_runtime" ] || [ -z "$_G_prefix" ]; then
print_help
exit 0
fi
if [[ "${_G_runmode[*]}" =~ "__srpt" ]]; then
setup_srpt "${@}"
fi
if [[ "${_G_runmode[*]}" =~ "__silent" ]]; then
suffix="> /dev/null 2>&1"
fi
if [[ "${_G_runmode[*]}" =~ "__mango" ]]; then
export MANGOHUD=1
fi
if [[ "${_G_runmode[*]}" =~ "__local" ]]; then
setup_network_block
fi
if [ ! -z "$_G_root" ]; then
cd "$_G_root" # change working dir to game root directory (as expected on windows)
fi
# Setup environment variables
setup_environment
main_exec="'$_G_runtime/proton'"
if [[ "${_G_runmode[*]}" =~ "__async" ]]; then
main_exec="$main_exec run"
else
main_exec="$main_exec waitforexitandrun"
fi
test -n "$_G_exec" && main_exec="$main_exec '$_G_exec' $_G_args"
# For test runs
if [[ "${_G_runmode[*]}" =~ "__dry" ]]; then
echo "STEAM_COMPAT_SHADER_PATH $STEAM_COMPAT_SHADER_PATH"
echo "STEAM_COMPAT_MOUNTS $STEAM_COMPAT_MOUNTS"
echo "$prefix $main_exec $suffix : $STEAM_COMPAT_DATA_PATH"
exit 0
fi
# Run proton instance (creates prefix if applies)
if [[ ! -e "$_G_prefix" ]] ; then
mkdir "$_G_prefix" || exit 1
eval "'$_G_runtime/proton' run wineboot --init"
fi
echo "$prefix : $main_exec : $suffix"
echo "Working dir: $PWD"
#read
eval "$prefix $main_exec $suffix"
[ ! -f "$_C_scriptDir/test_cases.sh" ] || . "$_C_scriptDir/test_cases.sh"
#sleep 600
echo "COMMAND: $prefix $main_exec $suffix"
echo "STEAM_COMPAT_APP_ID: $STEAM_COMPAT_APP_ID"

47
helper_steamct Executable file
View File

@ -0,0 +1,47 @@
#!/bin/bash
# Helper::Steam Compatibility Tools
# Expects below formats (called directly from steam client, supports any ambiguous application through chainloading)
# Launch current game while forcing native support (games steam doesn't list such feature for)
# $this waitforexitandrun /full/path/to/steam/game/binary
# Launch arbitrary EP process while emulating being a steam game in question (chainloading, may enable Remote Play Together etc.)
# $this waitforexitandrun /full/path/to/steam/game/binary "ENTRYPOINTNAME" --cd "ACTUALWORKINGDIR" ..ALLENTRYPOINTARGUMENTS..
_C_scriptName="$(basename -- "$(realpath -- "$0")")"
_C_scriptDir="$(dirname -- "$(realpath -- "$0")")"
# Support for generic native execution (no steam helpers support)
[ "$1" = "waitforexitandrun" ] || exit 0
args=("${@:2}")
# Support for routing arbitrary EP through current steam app (expects ep_* next to itself)
argIndex=0
for arg in "${args[@]}"; do
[[ "$arg" == "ep_"* ]] && break
((argIndex++))
done
if [ "${#args[@]}" -ne "$argIndex" ]; then
# Set correct Entry Point
argSwap=("${args[@]}")
args=("$_C_scriptDir/${argSwap[$argIndex]}")
((argIndex++))
# Restore expected working directory (if any)
if [[ "${argSwap[$argIndex]}" == "--cd" ]]; then
((argIndex++))
cd "${argSwap[$argIndex]}"
((argIndex++))
fi
# Set corrent args for Entry Point
args+=("${argSwap[@]:$argIndex}")
fi
# for arg in "${args[@]}"; do
# echo "ARG: $arg"
# done
# Execute requested command
echo "Command routed as [steam://run/$STEAM_COMPAT_APP_ID]:"
echo "cd $(pwd)"
echo "exec ${args[@]}"
exec "${args[@]}"

33
monitor_by_id.c Normal file
View File

@ -0,0 +1,33 @@
// gcc monitor_by_id.c -o monitor_by_id -lX11 -lXrandr
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int vmajor = 0;
int vminor = 0;
int moni = -1;
int monc = 0;
if (argc == 2) moni = atoi(argv[1]);
Display *dpy = XOpenDisplay(NULL);
if (!dpy || moni < 0) return 1;
Window wnd = XDefaultRootWindow(dpy);
if (XRRQueryExtension(dpy, &vmajor, &vminor))
{
XRRQueryVersion(dpy, &vmajor, &vminor);
XRRMonitorInfo *info = XRRGetMonitors(dpy, wnd, 0, &monc);
if (moni >= monc) return 1;
printf("%s\n", XGetAtomName(dpy, info[moni].name));
XFree(info);
}
XCloseDisplay(dpy);
return 0;
}

10
patch_pages Executable file
View File

@ -0,0 +1,10 @@
#!/bin/bash
shopt -s globstar
# Patch html
read -p "This action may modify all .html files at '$PWD'"
for html in **/*.html ; do
# Override relative links to open in current tab instead
sed -i 's~href="patcher/" target="_blank"~href="patcher/"~g' "$html"
done

11
proton.patch Normal file
View File

@ -0,0 +1,11 @@
--- upstream/proton
+++ mod/proton
@@ -1462,6 +1462,8 @@
prepend_to_env_str(self.env, ld_path_var, g_proton.lib64_dir + ":" + g_proton.lib_dir, ":")
self.env["WINEDLLPATH"] = g_proton.lib64_dir + "/wine:" + g_proton.lib_dir + "/wine"
+ if len(os.getenv("WINEDLLPATH") or ""):
+ self.env["WINEDLLPATH"] = os.getenv("WINEDLLPATH").strip(":") + ":" + self.env["WINEDLLPATH"]
self.env["GST_PLUGIN_SYSTEM_PATH_1_0"] = g_proton.lib64_dir + "gstreamer-1.0" + ":" + g_proton.lib_dir + "gstreamer-1.0"
self.env["WINE_GST_REGISTRY_DIR"] = g_compatdata.path("gstreamer-1.0/")

43
stacktrace.py Normal file
View File

@ -0,0 +1,43 @@
#!/usr/bin/python
# Translates wine stacktraces to static adresses (so at 18h*Fh^7)
# @1: append to old value (default 0)
# @2: fallback source VA (default 0x0)
# @3: fallback target VA (default 0x180000000)
import sys
OLDADDRESS = sys.argv[1] == "1" if len(sys.argv) >= 2 else False
VABASE_DEFAULT = int(sys.argv[2].rstrip("h"), 16) if len(sys.argv) >= 3 else 0x0
VATARGET_DEFAULT = int(sys.argv[3].rstrip("h"), 16) if len(sys.argv) >= 4 else 0x180000000
VABASE = VABASE_DEFAULT
VATARGET = VATARGET_DEFAULT
print(f"Fallback source VA: {hex(VABASE)}", file=sys.stderr)
print(f"Fallback target VA: {hex(VATARGET)}", file=sys.stderr)
for line in sys.stdin:
linebase = line
try:
if line.lower().strip().startswith("vabase:"):
# Reconfigure VA for next lines
valindex = line.lower().find("vabase:") + 7
src, target, *_ = [x.strip() if len(x.strip()) else None for x in line[valindex:].strip().split("->") + [""]]
if src == "SKIP":
VABASE = 0
VATARGET = 0
else:
VABASE = int(src.rstrip("h"), 16) if src else VABASE_DEFAULT
VATARGET = int(target.rstrip("h"), 16) if target else VATARGET_DEFAULT
line = f"{line[:valindex]} {hex(VABASE)} -> {hex(VATARGET)}"
elif VABASE == 0 and VATARGET == 0:
# Lines to be untouched
raise
else:
# Lines to be translated
srcaddrstr = line.strip()[:16]
valindex = line.find(srcaddrstr)
tgtaddr = VATARGET + int(srcaddrstr, 16) - VABASE
tgtaddrstr=f"{hex(tgtaddr)} : {srcaddrstr}" if OLDADDRESS else f"{hex(tgtaddr)}"
line = f"{line[:valindex]}{tgtaddrstr}{line[valindex+16:].rstrip()}"
print(f"{line}")
except:
print(f"{linebase}", end="")