nixcitizen/default.nix

233 lines
7.3 KiB
Nix

{ stdenv, lib, pkgs, fetchurl, fetchpatch, nix, pkgsCross,
installDir ? "$HOME/.local/starcitizen",
launcherCache ? "$HOME/.local/share",
prefixBaseDir ? "$HOME/.winenix",
binName ? "starcitizen",
launcherArgs ? [ "--use-gl=osmesa" ],
vulkanDrivers ? [ ],
dxvkPatches ? [ ],
dxvkAsync ? false,
winePackage ? pkgs.wineWowPackages.staging,
wineSrc ? null,
wineGlobalEnv ? [ "DXVK_STATE_CACHE=0" ],
winePatches ? [],
applyReccomendedWinePatches ? true,
virtualDesktop ? null,
registryFiles ? [ ],
captureMouse ? true,
enableGameScope ? false,
gameScopeArgs ? [ "-W 2560" "-H 1440" "-b" ],
}:
#check wether string is two positive integers separated by x
assert virtualDesktop == null ||
(lib.strings.toInt(lib.strings.concatStrings(lib.strings.splitString "x" virtualDesktop))) > 0;
#check whether paths are not terminated with a /
assert !(builtins.any (lib.strings.hasSuffix "/") [ installDir launcherCache prefixBaseDir ]);
let
wineReccomendedPatches = [
(fetchpatch {
name = "ernel32-SetThreadInformation-stub";
url = "https://gist.githubusercontent.com/ananace/1139461949d532fea812ac53a6b016bb/raw/5e343820890acb7a2e9b49cc3cf7a6703694bffa/kernel32-SetThreadInformation-stub.mypatch";
sha256 = "sha256-2FfHFu8juzIVMUsKgfu2hgA0u017bDQiie9RHxMgh4g=";
})
];
winePkg = winePackage.overrideDerivation (attrs: {
patches = (if wineSrc == null then attrs.patches else []) ++ winePatches ++ lib.optional applyReccomendedWinePatches wineReccomendedPatches;
disabledPatchsets = [ "ntdll-*" ];
src = if wineSrc != null then wineSrc else attrs.src;
});
dxvk = (pkgsCross.mingwW64.callPackage ./dxvk.nix { async = dxvkAsync; }).overrideAttrs
( attrs: { patches = attrs.patches ++ dxvkPatches; });
dxvkAsyncEnv = "DXVK_ASYNC=1" ;
gamescope = "${pkgs.callPackage ./gamescope.nix {}}/bin/gamescope";
vulkanDriverPaths = {
radeon = "${pkgs.mesa_drivers.drivers}/share/vulkan/icd.d/radeon_icd.x86_64.json";
intel = "${pkgs.mesa_drivers.drivers}/share/vulkan/icd.d/intel_icd.x86_64.json";
amdvlk = "${pkgs.amdvlk}/share/vulkan/icd.d/amd_icd64.json";
};
vkIcd = lib.strings.concatStringsSep ":" (lib.attrsets.attrVals vulkanDrivers vulkanDriverPaths);
fonts = pkgs.callPackage ./fonts.nix {};
rsiInstaller = fetchurl {
url = "https://install.robertsspaceindustries.com/star-citizen/RSI-Setup-1.5.5.exe";
sha256 = "sha256-w0pLj0/awT4nmDpG8INSbjVQM63zCRvUUJ/36+r/JrE=";
};
vcrun2019 = fetchurl {
url = "https://aka.ms/vs/16/release/vc_redist.x86.exe";
sha256 = "sha256-TGxCDPTL8snJ7UdullgK6SqXsoIsITKaLknoQ5rFrTA=";
};
win10Reg = pkgs.writeTextFile {
name = "win10.reg";
text = ./win10.reg;
};
captureMouseReg = pkgs.writeTextFile {
name = "captureMouse.reg";
text = ./captureMouse.reg;
};
helpText = pkgs.writeTextFile {
name = "scHelptext";
text = ./helpText.txt;
};
wine64 = "${winePkg}/bin/wine64";
wineMulti = "${winePkg}/bin/wine";
regEdit = "${wine64} regedit";
reg = "${wine64} reg";
script = pkgs.writeShellScriptBin binName ''
#sane bash
set -eo pipefail
function installPrefix () {
if [ ! -d "$WINEPREFIX" ]; then
${winePkg}/bin/wineboot -i
#set win 10
${regEdit} ${win10Reg}
#install dxvk
for library in ${dxvk}/bin/*.dll ; do
cp $library "$WINEPREFIX/drive_c/windows/system32"
local libraryFile=$(basename $library)
${reg} add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v ''${libraryFile/\.dll/} /d native /f
done
#install fonts
cp ${fonts}/share/fonts/*.TTF "$WINEPREFIX/drive_c/windows/Fonts"
${regEdit} ${fonts}/share/regs/fonts.reg
#install vcrun2019
${wineMulti} ${vcrun2019} /q
#symlink persistent game and launcher binaries into prefix.
gameBinariesPers="${installDir}/Roberts Space Industries"
gameBinariesLinkDest="$WINEPREFIX/drive_c/Program Files/"
mkdir -p "$gameBinariesPers" "$gameBinariesLinkDest"
ln -s "$gameBinariesPers" "$gameBinariesLinkDest"
#symlink launcher cache
launcherCachePers="${launcherCache}/rsilauncher"
mkdir -p "$launcherCachePers" "$WINEPREFIX/drive_c/users/$USER/AppData/Roaming/"
ln -s "$launcherCachePers" "$WINEPREFIX/drive_c/users/$USER/AppData/Roaming/"
${lib.optionalString captureMouse "${regEdit} ${captureMouseReg.text}"}
#apply custom user registry files
${lib.concatMapStrings (x: "${regEdit} " + x + "\n") registryFiles}
fi
}
function installLauncher () {
installPrefix
#install the launcher
echo "Install with default parameters, launcherArgs won't be used when you launch the launcher from the setup"
${winePkg}/bin/wine ${rsiInstaller}
}
function runGame () {
installPrefix
#install the launcher conditionally here and not in the launcher to allow force reinstalls.
if [ ! -f "${installDir}/Roberts Space Industries/RSI Launcher/RSI Launcher.exe" ]; then
installLauncher
fi
${lib.optionalString enableGameScope "${gamescope} ${builtins.concatStringsSep " " gameScopeArgs} --\\" }
${wineMulti} \
${lib.optionalString (virtualDesktop != null) "explorer /desktop=${binName},${virtualDesktop}"} \
"$WINEPREFIX/drive_c/Program Files/Roberts Space Industries/RSI Launcher/RSI Launcher.exe" \
${lib.concatStringsSep " " launcherArgs}
}
function printPrefix () {
echo "$WINEPREFIX"
}
function clean () {
find "${prefixBaseDir}" -maxdepth 1 -type d -name ????????????????????????????????-"${binName}" -and -not -wholename "$WINEPREFIX" -exec rm -rf {} \;
}
function removePrefix () {
#Good thing the GPL contains a no warranty clause
rm -rf "$WINEPREFIX"
}
function help () {
cat ${helpText.text}
}
function wine () {
installPrefix
${winePkg}/bin/"$@"
}
#base setup
if [ ! -d "${installDir}" ]; then
mkdir -p "${installDir}/Roberts Space Industries"
fi
#create base dir for nix installs
if [ ! -d ${prefixBaseDir} ]; then
mkdir -p "${prefixBaseDir}"
fi
#core idea: Generate UUID from storage path of this script, ensure
#new prefix for any changes. Needs fast prefix installs and state outside.
uuid=$(basename $(${pkgs.nix}/bin/nix path-info "$(readlink -f $BASH_SOURCE)"))
export WINEPREFIX="${prefixBaseDir}/$uuid"
export WINEARCH=win64
#optionally export vulkan drivers:
#The following line might be empty in the resulting script.
# ${lib.optionalString (vulkanDrivers != []) "export VK_ICD_FILENAMES=${vkIcd}"}
#export all global env vars
${lib.concatMapStrings (x: "export " + x + "\n") (wineGlobalEnv
++ lib.lists.optional dxvkAsync dxvkAsyncEnv
)}
#parse input
case "$@" in
--install-prefix)
installPrefix
;;
--install-launcher)
installLauncher
;;
--clean)
clean
;;
--remove-prefix)
removePrefix
;;
--run-game|"")
runGame
;;
--print-prefix)
printPrefix
;;
--help)
help
;;
--wine*)
shift
wine "$@"
;;
*)
help
exit 1
esac
'';
in script