diff --git a/modules/apps/gaming.nix b/modules/apps/gaming.nix index 0fae952..141243c 100644 --- a/modules/apps/gaming.nix +++ b/modules/apps/gaming.nix @@ -12,29 +12,31 @@ platformOptimizations.enable = true; }; }; - users.users.jawz.packages = - let polymc = pkgs.callPackage ../../pkgs/polymc/default.nix { }; - in (with pkgs; [ - mangohud # fps & stats overlay - lutris # games launcher & emulator hub - cartridges # games launcher - gamemode # optimizes linux to have better gaming performance - heroic # install epic games - protonup-qt # update proton-ge - #minecraft # minecraft official launcher - ns-usbloader # load games into my switch - # grapejuice # roblox manager + users.users.jawz.packages = let + polymc = pkgs.callPackage ../../pkgs/polymc/default.nix { }; + citra-nightly = + pkgs.callPackage ../../pkgs/citra/default.nix { branch = "nightly"; }; + in (with pkgs; [ + mangohud # fps & stats overlay + lutris # games launcher & emulator hub + cartridges # games launcher + gamemode # optimizes linux to have better gaming performance + heroic # install epic games + protonup-qt # update proton-ge + #minecraft # minecraft official launcher + ns-usbloader # load games into my switch + # grapejuice # roblox manager - # emulators - rpcs3 # ps3 emulator - pcsx2 # ps2 emulator - cemu # wii u emulator - dolphin-emu # wii emulator - #citra-nightly # 3Ds emulator - snes9x-gtk # snes emulator - ryujinx # switch emulator - ]) ++ [ - polymc # minecraft launcher with mod support - ]; + # emulators + rpcs3 # ps3 emulator + pcsx2 # ps2 emulator + cemu # wii u emulator + dolphin-emu # wii emulator + snes9x-gtk # snes emulator + ryujinx # switch emulator + ]) ++ [ + citra-nightly # 3Ds emulator + polymc # minecraft launcher with mod support + ]; }; } diff --git a/pkgs/citra/default.nix b/pkgs/citra/default.nix new file mode 100644 index 0000000..cc22c44 --- /dev/null +++ b/pkgs/citra/default.nix @@ -0,0 +1,27 @@ +{ branch, qt6Packages, fetchFromGitHub, fetchurl }: + +let + # Fetched from https://api.citra-emu.org/gamedb + # Please make sure to update this when updating citra! + compat-list = fetchurl { + name = "citra-compat-list"; + url = + "https://web.archive.org/web/20230807103651/https://api.citra-emu.org/gamedb/"; + hash = "sha256-J+zqtWde5NgK2QROvGewtXGRAWUTNSKHNMG6iu9m1fU="; + }; +in { + nightly = qt6Packages.callPackage ./generic.nix rec { + pname = "citra-nightly"; + version = "2104"; + + src = fetchFromGitHub { + owner = "Nailington"; + repo = "Citra-Nightly"; + rev = "nightly-${version}"; + sha256 = "0ggi1l8327s43xaxs616g0s9vmal6q7vsv69bn07gp71gchhcmyi"; + fetchSubmodules = true; + }; + + inherit branch compat-list; + }; +}.${branch} diff --git a/pkgs/citra/generic.nix b/pkgs/citra/generic.nix new file mode 100644 index 0000000..e10b63c --- /dev/null +++ b/pkgs/citra/generic.nix @@ -0,0 +1,96 @@ +{ pname, version, src, branch, compat-list, lib, stdenv, cmake, boost +, pkg-config, libusb1, glslang, zstd, libressl, enableSdl2 ? true, SDL2 +, enableQt ? true, qtbase, qtmultimedia, wrapQtAppsHook +, enableQtTranslation ? enableQt, qttools, enableWebService ? true +, enableCubeb ? true, cubeb, enableFfmpegAudioDecoder ? true +, enableFfmpegVideoDumper ? true, ffmpeg_4, useDiscordRichPresence ? true +, rapidjson, enableFdk ? false, fdk_aac, python3 }: +assert lib.assertMsg (!enableFfmpegAudioDecoder || !enableFdk) + "Can't enable both enableFfmpegAudioDecoder and enableFdk"; + +stdenv.mkDerivation rec { + inherit pname version src; + + nativeBuildInputs = [ cmake glslang pkg-config python3 ] + ++ lib.optionals enableQt [ wrapQtAppsHook ]; + + buildInputs = [ boost libusb1 ] + ++ lib.optionals enableQt [ qtbase qtmultimedia ] + ++ lib.optional enableSdl2 SDL2 ++ lib.optional enableQtTranslation qttools + ++ lib.optionals enableCubeb cubeb.passthru.backendLibs + ++ lib.optional (enableFfmpegAudioDecoder || enableFfmpegVideoDumper) + ffmpeg_4 ++ lib.optional useDiscordRichPresence rapidjson + ++ lib.optional enableFdk fdk_aac; + + cmakeFlags = [ + "-DUSE_SYSTEM_BOOST=ON" + "-DCITRA_WARNINGS_AS_ERRORS=OFF" + "-DCITRA_USE_BUNDLED_FFMPEG=OFF" + "-DCITRA_USE_BUNDLED_QT=OFF" + "-DUSE_SYSTEM_SDL2=ON" + "-DCMAKE_INSTALL_INCLUDEDIR=include" + "-DCMAKE_INSTALL_LIBDIR=lib" + + # We dont want to bother upstream with potentially outdated compat reports + "-DCITRA_ENABLE_COMPATIBILITY_REPORTING=ON" + "-DENABLE_COMPATIBILITY_LIST_DOWNLOAD=OFF" # We provide this deterministically + ] ++ lib.optional (!enableSdl2) "-DENABLE_SDL2=OFF" + ++ lib.optional (!enableQt) "-DENABLE_QT=OFF" + ++ lib.optional enableQtTranslation "-DENABLE_QT_TRANSLATION=ON" + ++ lib.optional (!enableWebService) "-DENABLE_WEB_SERVICE=OFF" + ++ lib.optional (!enableCubeb) "-DENABLE_CUBEB=OFF" + ++ lib.optional enableFfmpegAudioDecoder "-DENABLE_FFMPEG_AUDIO_DECODER=ON" + ++ lib.optional enableFfmpegVideoDumper "-DENABLE_FFMPEG_VIDEO_DUMPER=ON" + ++ lib.optional useDiscordRichPresence "-DUSE_DISCORD_PRESENCE=ON" + ++ lib.optional enableFdk "-DENABLE_FDK=ON"; + + postPatch = let + branchCaptialized = + (lib.toUpper (lib.substring 0 1 branch) + lib.substring 1 (-1) branch); + in '' + # Fix file not found when looking in var/empty instead of opt + mkdir externals/dynarmic/src/dynarmic/ir/var + ln -s ../opt externals/dynarmic/src/dynarmic/ir/var/empty + + # Prep compatibilitylist + ln -s ${compat-list} ./dist/compatibility_list/compatibility_list.json + + # We already know the submodules are present + substituteInPlace CMakeLists.txt \ + --replace "check_submodules_present()" "" + + # Add versions + echo 'set(BUILD_FULLNAME "${branchCaptialized} ${version}")' >> CMakeModules/GenerateBuildInfo.cmake + + # Devendoring + rm -rf externals/zstd externals/libressl + cp -r ${zstd.src} externals/zstd + tar xf ${libressl.src} -C externals/ + mv externals/${libressl.name} externals/libressl + chmod -R a+w externals/zstd + ''; + + # Fixes https://github.com/NixOS/nixpkgs/issues/171173 + postInstall = lib.optionalString (enableCubeb && enableSdl2) '' + wrapProgram "$out/bin/citra" \ + --prefix LD_LIBRARY_PATH : ${ + lib.makeLibraryPath cubeb.passthru.backendLibs + } + ''; + + meta = { + homepage = "https://citra-emu.org"; + description = + "The ${branch} branch of an open-source emulator for the Ninteno 3DS"; + longDescription = '' + A Nintendo 3DS Emulator written in C++ + Using the nightly branch is recommended for general usage. + Using the canary branch is recommended if you would like to try out + experimental features, with a cost of stability. + ''; + mainProgram = if enableQt then "citra-qt" else "citra"; + platforms = lib.platforms.linux; + license = lib.licenses.gpl2Plus; + maintainers = with lib.maintainers; [ abbradar ashley ivar ]; + }; +} diff --git a/pkgs/citra/update.sh b/pkgs/citra/update.sh new file mode 100644 index 0000000..e76121d --- /dev/null +++ b/pkgs/citra/update.sh @@ -0,0 +1,84 @@ +#! /usr/bin/env nix-shell +#! nix-shell -i bash -p nix nix-prefetch-git coreutils curl jq gnused + +set -euo pipefail + +# Will be replaced with the actual branch when running this from passthru.updateScript +BRANCH="@branch@" + +if [[ ! "$(basename $PWD)" = "citra" ]]; then + echo "error: Script must be ran from citra's directory!" + exit 1 +fi + +getLocalVersion() { + pushd ../../../.. >/dev/null + nix eval --raw -f default.nix "$1".version + popd >/dev/null +} + +getLocalHash() { + pushd ../../../.. >/dev/null + nix eval --raw -f default.nix "$1".src.drvAttrs.outputHash + popd >/dev/null +} + +updateNightly() { + OLD_NIGHTLY_VERSION="$(getLocalVersion "citra-nightly")" + OLD_NIGHTLY_HASH="$(getLocalHash "citra-nightly")" + + NEW_NIGHTLY_VERSION="$(curl -s ${GITHUB_TOKEN:+-u ":$GITHUB_TOKEN"} \ + "https://api.github.com/repos/citra-emu/citra-nightly/releases?per_page=1" | jq -r '.[0].name' | cut -d"-" -f2 | cut -d" " -f2)" + + if [[ "${OLD_NIGHTLY_VERSION}" = "${NEW_NIGHTLY_VERSION}" ]]; then + echo "citra-nightly is already up to date!" + + [ "$KEEP_GOING" ] && return || exit + else + echo "citra-nightly: ${OLD_NIGHTLY_VERSION} -> ${NEW_NIGHTLY_VERSION}" + fi + + echo " Fetching source code..." + + NEW_NIGHTLY_HASH="$(nix-prefetch-git --quiet --fetch-submodules --rev "nightly-${NEW_NIGHTLY_VERSION}" "https://github.com/citra-emu/citra-nightly" | jq -r '.sha256')" + + echo " Successfully fetched. hash: ${NEW_NIGHTLY_HASH}" + + sed -i "s|${OLD_NIGHTLY_VERSION}|${NEW_NIGHTLY_VERSION}|" ./default.nix + sed -i "s|${OLD_NIGHTLY_HASH}|${NEW_NIGHTLY_HASH}|" ./default.nix +} + +updateCanary() { + OLD_CANARY_VERSION="$(getLocalVersion "citra-canary")" + OLD_CANARY_HASH="$(getLocalHash "citra-canary")" + + NEW_CANARY_VERSION="$(curl -s ${GITHUB_TOKEN:+-u ":$GITHUB_TOKEN"} \ + "https://api.github.com/repos/citra-emu/citra-canary/releases?per_page=1" | jq -r '.[0].name' | cut -d"-" -f2 | cut -d" " -f1)" + + if [[ "${OLD_CANARY_VERSION}" = "${NEW_CANARY_VERSION}" ]]; then + echo "citra-canary is already up to date!" + + [ "$KEEP_GOING" ] && return || exit + else + echo "citra-canary: ${OLD_CANARY_VERSION} -> ${NEW_CANARY_VERSION}" + fi + + echo " Fetching source code..." + + NEW_CANARY_HASH="$(nix-prefetch-git --quiet --fetch-submodules --rev "canary-${NEW_CANARY_VERSION}" "https://github.com/citra-emu/citra-canary" | jq -r '.sha256')" + + echo " Successfully fetched. hash: ${NEW_CANARY_HASH}" + + sed -i "s|${OLD_CANARY_VERSION}|${NEW_CANARY_VERSION}|" ./default.nix + sed -i "s|${OLD_CANARY_HASH}|${NEW_CANARY_HASH}|" ./default.nix +} + +if [[ "$BRANCH" = "nightly" ]]; then + updateNightly +elif [[ "$BRANCH" = "early-access" ]]; then + updateCanary +else + KEEP_GOING=1 + updateNightly + updateCanary +fi