From 8ea5d3ba0b1d6ed51b41f4dc6f4dd8b20c3734f1 Mon Sep 17 00:00:00 2001 From: Jasi Date: Fri, 15 Aug 2025 21:55:32 -0400 Subject: [PATCH 1/2] spirv-cross: build shared libraries on linux platforms --- pkgs/by-name/sp/spirv-cross/package.nix | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/by-name/sp/spirv-cross/package.nix b/pkgs/by-name/sp/spirv-cross/package.nix index 20b464dd5ea0e..4f721392245f6 100644 --- a/pkgs/by-name/sp/spirv-cross/package.nix +++ b/pkgs/by-name/sp/spirv-cross/package.nix @@ -22,6 +22,10 @@ stdenv.mkDerivation (finalAttrs: { python3 ]; + cmakeFlags = lib.optionals stdenv.hostPlatform.isLinux [ + (lib.cmakeBool "SPIRV_CROSS_SHARED" true) + ]; + postFixup = '' substituteInPlace $out/lib/pkgconfig/*.pc \ --replace '=''${prefix}//' '=/' From fdbdc038adce62174243da7736a99baef00cf333 Mon Sep 17 00:00:00 2001 From: Jasi Date: Mon, 11 Aug 2025 22:07:53 -0400 Subject: [PATCH 2/2] duckstation-unofficial: init at 0.1-9483 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a soft-revert of duckstation's removal in #430501 (revision: f5cb574f4221ba0aa0df5da3d377f8315f557d0c) and placing it under the `duckstation-unofficial` attribute which supports both linux and darwin platforms, most of the previously submitted code and patches still apply and this commit squashes everything together into one package file and thus is a combination of work done by different authors, listed below to the best of my ability: Co-developed-by: Marcin Serwin Co-developed-by: Anderson Torres Co-developed-by: OPNA2608 Co-developed-by: qubitnano <146656568+qubitnano@users.noreply.github.com> Co-developed-by: PedroHLC ☭ Co-developed-by: Artturin Co-developed-by: Guillaume Bouchard --- .../0001-remove-cubeb-vendor.patch | 34 ++ .../0002-fix-NEON-intrinsics.patch | 70 ++++ .../du/duckstation-unofficial/package.nix | 331 ++++++++++++++++++ .../du/duckstation-unofficial/sources.json | 20 ++ .../du/duckstation-unofficial/update.sh | 74 ++++ 5 files changed, 529 insertions(+) create mode 100644 pkgs/by-name/du/duckstation-unofficial/0001-remove-cubeb-vendor.patch create mode 100644 pkgs/by-name/du/duckstation-unofficial/0002-fix-NEON-intrinsics.patch create mode 100644 pkgs/by-name/du/duckstation-unofficial/package.nix create mode 100644 pkgs/by-name/du/duckstation-unofficial/sources.json create mode 100755 pkgs/by-name/du/duckstation-unofficial/update.sh diff --git a/pkgs/by-name/du/duckstation-unofficial/0001-remove-cubeb-vendor.patch b/pkgs/by-name/du/duckstation-unofficial/0001-remove-cubeb-vendor.patch new file mode 100644 index 0000000000000..f3d745bb055f0 --- /dev/null +++ b/pkgs/by-name/du/duckstation-unofficial/0001-remove-cubeb-vendor.patch @@ -0,0 +1,34 @@ +diff --git a/dep/CMakeLists.txt b/dep/CMakeLists.txt +index 633267c66..8f9c65c39 100644 +--- a/dep/CMakeLists.txt ++++ b/dep/CMakeLists.txt +@@ -25,9 +25,9 @@ add_subdirectory(rcheevos EXCLUDE_FROM_ALL) + disable_compiler_warnings_for_target(rcheevos) + add_subdirectory(rapidyaml EXCLUDE_FROM_ALL) + disable_compiler_warnings_for_target(rapidyaml) +-add_subdirectory(cubeb EXCLUDE_FROM_ALL) +-disable_compiler_warnings_for_target(cubeb) +-disable_compiler_warnings_for_target(speex) ++find_package(cubeb REQUIRED GLOBAL) ++add_library(cubeb ALIAS cubeb::cubeb) ++# disable_compiler_warnings_for_target(speex) + + if(ENABLE_OPENGL) + add_subdirectory(glad EXCLUDE_FROM_ALL) +diff --git a/src/util/cubeb_audio_stream.cpp b/src/util/cubeb_audio_stream.cpp +index e01cbfe78..294c6e59d 100644 +--- a/src/util/cubeb_audio_stream.cpp ++++ b/src/util/cubeb_audio_stream.cpp +@@ -261,9 +261,9 @@ std::vector> AudioStream::GetCubebDriverName + std::vector> names; + names.emplace_back(std::string(), TRANSLATE_STR("AudioStream", "Default")); + +- const char** cubeb_names = cubeb_get_backend_names(); +- for (u32 i = 0; cubeb_names[i] != nullptr; i++) +- names.emplace_back(cubeb_names[i], cubeb_names[i]); ++ cubeb_backend_names cubeb_names = cubeb_get_backend_names(); ++ for (u32 i = 0; i < cubeb_names.count; i++) ++ names.emplace_back(cubeb_names.names[i], cubeb_names.names[i]); + return names; + } + diff --git a/pkgs/by-name/du/duckstation-unofficial/0002-fix-NEON-intrinsics.patch b/pkgs/by-name/du/duckstation-unofficial/0002-fix-NEON-intrinsics.patch new file mode 100644 index 0000000000000..571a15d4aad62 --- /dev/null +++ b/pkgs/by-name/du/duckstation-unofficial/0002-fix-NEON-intrinsics.patch @@ -0,0 +1,70 @@ +From 19e094e5c7aaaf375a13424044521701e85c8313 Mon Sep 17 00:00:00 2001 +From: OPNA2608 +Date: Thu, 9 Jan 2025 17:46:25 +0100 +Subject: [PATCH] Fix usage of NEON intrinsics + +--- + src/common/gsvector_neon.h | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/common/gsvector_neon.h b/src/common/gsvector_neon.h +index e4991af5e..61b8dc09b 100644 +--- a/src/common/gsvector_neon.h ++++ b/src/common/gsvector_neon.h +@@ -867,7 +867,7 @@ public: + + ALWAYS_INLINE int mask() const + { +- const uint32x2_t masks = vshr_n_u32(vreinterpret_u32_s32(v2s), 31); ++ const uint32x2_t masks = vshr_n_u32(vreinterpret_u32_f32(v2s), 31); + return (vget_lane_u32(masks, 0) | (vget_lane_u32(masks, 1) << 1)); + } + +@@ -2882,7 +2882,7 @@ public: + ALWAYS_INLINE GSVector4 gt64(const GSVector4& v) const + { + #ifdef CPU_ARCH_ARM64 +- return GSVector4(vreinterpretq_f32_f64(vcgtq_f64(vreinterpretq_f64_f32(v4s), vreinterpretq_f64_f32(v.v4s)))); ++ return GSVector4(vreinterpretq_f32_u64(vcgtq_f64(vreinterpretq_f64_f32(v4s), vreinterpretq_f64_f32(v.v4s)))); + #else + GSVector4 ret; + ret.U64[0] = (F64[0] > v.F64[0]) ? 0xFFFFFFFFFFFFFFFFULL : 0; +@@ -2894,7 +2894,7 @@ public: + ALWAYS_INLINE GSVector4 eq64(const GSVector4& v) const + { + #ifdef CPU_ARCH_ARM64 +- return GSVector4(vreinterpretq_f32_f64(vceqq_f64(vreinterpretq_f64_f32(v4s), vreinterpretq_f64_f32(v.v4s)))); ++ return GSVector4(vreinterpretq_f32_u64(vceqq_f64(vreinterpretq_f64_f32(v4s), vreinterpretq_f64_f32(v.v4s)))); + #else + GSVector4 ret; + ret.U64[0] = (F64[0] == v.F64[0]) ? 0xFFFFFFFFFFFFFFFFULL : 0; +@@ -2906,7 +2906,7 @@ public: + ALWAYS_INLINE GSVector4 lt64(const GSVector4& v) const + { + #ifdef CPU_ARCH_ARM64 +- return GSVector4(vreinterpretq_f32_f64(vcgtq_f64(vreinterpretq_f64_f32(v4s), vreinterpretq_f64_f32(v.v4s)))); ++ return GSVector4(vreinterpretq_f32_u64(vcgtq_f64(vreinterpretq_f64_f32(v4s), vreinterpretq_f64_f32(v.v4s)))); + #else + GSVector4 ret; + ret.U64[0] = (F64[0] < v.F64[0]) ? 0xFFFFFFFFFFFFFFFFULL : 0; +@@ -2918,7 +2918,7 @@ public: + ALWAYS_INLINE GSVector4 ge64(const GSVector4& v) const + { + #ifdef CPU_ARCH_ARM64 +- return GSVector4(vreinterpretq_f32_f64(vcgeq_f64(vreinterpretq_f64_f32(v4s), vreinterpretq_f64_f32(v.v4s)))); ++ return GSVector4(vreinterpretq_f32_u64(vcgeq_f64(vreinterpretq_f64_f32(v4s), vreinterpretq_f64_f32(v.v4s)))); + #else + GSVector4 ret; + ret.U64[0] = (F64[0] >= v.F64[0]) ? 0xFFFFFFFFFFFFFFFFULL : 0; +@@ -2930,7 +2930,7 @@ public: + ALWAYS_INLINE GSVector4 le64(const GSVector4& v) const + { + #ifdef CPU_ARCH_ARM64 +- return GSVector4(vreinterpretq_f32_f64(vcleq_f64(vreinterpretq_f64_f32(v4s), vreinterpretq_f64_f32(v.v4s)))); ++ return GSVector4(vreinterpretq_f32_u64(vcleq_f64(vreinterpretq_f64_f32(v4s), vreinterpretq_f64_f32(v.v4s)))); + #else + GSVector4 ret; + ret.U64[0] = (F64[0] <= v.F64[0]) ? 0xFFFFFFFFFFFFFFFFULL : 0; +-- +2.47.0 + diff --git a/pkgs/by-name/du/duckstation-unofficial/package.nix b/pkgs/by-name/du/duckstation-unofficial/package.nix new file mode 100644 index 0000000000000..0ca7e5a37b7fc --- /dev/null +++ b/pkgs/by-name/du/duckstation-unofficial/package.nix @@ -0,0 +1,331 @@ +{ + lib, + llvmPackages, + stdenvNoCC, + fetchFromGitHub, + cmake, + pkg-config, + ninja, + extra-cmake-modules, + wayland-scanner, + makeBinaryWrapper, + qt6, + sdl3, + zstd, + libwebp, + zlib, + libpng, + libjpeg, + freetype, + plutosvg, + cpuinfo, + soundtouch, + rapidjson, + cubeb, + libzip, + curl, + libX11, + wayland, + shaderc, + spirv-cross, + udev, + libbacktrace, + ffmpeg-headless, + fetchurl, + zip, + unzip, +}: + +let + passthru = { + updateScript = ./update.sh; + }; + + meta = { + description = "Fast PlayStation 1 emulator for x86-64/AArch32/AArch64/RV64"; + longDescription = '' + # DISCLAIMER + This is an **unofficial** package, do not report any issues to + duckstation developers. Instead, please report them to + or use the officially + supported platform build at or other + upstream-approved distribution mechanism not listed here. We + (nixpkgs) do not endorse or condone any action taken on your own + accord in regards to this package. + ''; + homepage = "https://duckstation.org"; + license = lib.licenses.cc-by-nc-nd-40; + maintainers = with lib.maintainers; [ normalcea ]; + }; + + pkgSources = lib.importJSON ./sources.json; + + linuxDrv = llvmPackages.stdenv.mkDerivation (finalAttrs: { + pname = "duckstation-unofficial"; + version = pkgSources.duckstation.version; + + src = fetchFromGitHub { + owner = "stenzek"; + repo = "duckstation"; + tag = "v${finalAttrs.version}"; + hash = pkgSources.duckstation.hash_linux; + }; + + patches = [ + ./0001-remove-cubeb-vendor.patch + ./0002-fix-NEON-intrinsics.patch + ]; + + vendorDiscordRPC = llvmPackages.stdenv.mkDerivation { + pname = "discord-rpc-duckstation"; + inherit (finalAttrs) version; + src = fetchFromGitHub { + owner = "stenzek"; + repo = "discord-rpc"; + rev = pkgSources.discord_rpc.rev; + hash = pkgSources.discord_rpc.hash; + }; + nativeBuildInputs = [ cmake ]; + buildInputs = [ rapidjson ]; + meta = { + license = lib.licenses.mit; + platforms = lib.platforms.linux; + }; + }; + + vendorShaderc = shaderc.overrideAttrs (oldAttrs: { + pname = "shaderc-duckstation"; + inherit (finalAttrs) version; + src = fetchFromGitHub { + owner = "stenzek"; + repo = "shaderc"; + rev = pkgSources.shaderc.rev; + hash = pkgSources.shaderc.hash; + }; + + patches = (oldAttrs.patches or [ ]); + cmakeFlags = (oldAttrs.cmakeFlags or [ ]) ++ [ + (lib.cmakeBool "SHADERC_SKIP_EXAMPLES" true) + (lib.cmakeBool "SHADERC_SKIP_TESTS" true) + ]; + outputs = [ + "out" + "lib" + "dev" + ]; + postFixup = null; + }); + + soundtouch = llvmPackages.stdenv.mkDerivation { + inherit (soundtouch) + pname + version + src + meta + ; + nativeBuildInputs = [ cmake ]; + postPatch = '' + substituteInPlace CMakeLists.txt \ + --replace-fail "\''${prefix}/''${CMAKE_INSTALL_LIBDIR}" \ + "''${CMAKE_INSTALL_FULL_LIBDIR}" + ''; + + cmakeFlags = [ + (lib.cmakeBool "SOUNDTOUCH_DLL" true) + ]; + }; + + chtdb = stdenvNoCC.mkDerivation { + pname = "chtdb-duckstation"; + version = "0-unstable-${pkgSources.chtdb.date}"; + + src = fetchFromGitHub { + owner = "duckstation"; + repo = "chtdb"; + rev = pkgSources.chtdb.rev; + hash = pkgSources.chtdb.hash; + }; + + nativeBuildInputs = [ + zip + ]; + + buildPhase = '' + runHook preBuild + + pushd cheats + zip -r cheats.zip *.cht + popd + pushd patches + zip -r patches.zip *.cht + popd + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + install -Dm644 cheats/cheats.zip -t $out/lib/duckstation + install -Dm644 patches/patches.zip -t $out/lib/duckstation + + install -Dm644 LICENSE -t $out/share/doc/duckstation + install -Dm644 README.md -t $out/share/doc/duckstation + + runHook postInstall + ''; + + meta = { + description = "Collection of cheats and patches for PSX games"; + longDescription = '' + Collection of cheats and patches for PSX games, primarily intended for + use with the DuckStation emulator, but can also be used by other + emulators that support GameShark codes. + + Patches show in the UI in a separate section to cheats, and are + intended for modifications to the game that do not provide any + "advantage" to the player, including: + + - Improving performance. + - Fixing game-breaking bugs. + - Unlocking the frame rate (e.g. "60 FPS patches"). + - Widescreen rendering where the built-in widescreen rendering rendering is insufficient. + ''; + license = lib.licenses.mit; + inherit (meta) maintainers; + platforms = lib.platforms.all; + }; + }; + + preConfigure = '' + cp ${finalAttrs.chtdb}/lib/duckstation/cheats.zip data/resources + cp ${finalAttrs.chtdb}/lib/duckstation/patches.zip data/resources + ''; + + nativeBuildInputs = [ + cmake + pkg-config + ninja + extra-cmake-modules + wayland-scanner + makeBinaryWrapper + qt6.wrapQtAppsHook + qt6.qttools + ]; + + buildInputs = [ + sdl3 + zstd + libwebp + zlib + libpng + libjpeg + freetype + plutosvg + cubeb + cpuinfo + libzip + curl + libX11 + wayland + spirv-cross + qt6.qtbase + udev + libbacktrace + ffmpeg-headless + ] + ++ [ + finalAttrs.vendorDiscordRPC + finalAttrs.vendorShaderc + finalAttrs.soundtouch + ]; + + cmakeFlags = [ + (lib.cmakeBool "ALLOW_INSTALL" true) + (lib.cmakeFeature "CMAKE_INSTALL_PREFIX" "${placeholder "out"}/lib/duckstation") + ]; + + qtWrapperArgs = [ + "--prefix LD_LIBRARY_PATH : ${(lib.makeLibraryPath [ ffmpeg-headless ])}" + ]; + + postInstall = '' + makeWrapper $out/lib/duckstation/duckstation-qt $out/bin/duckstation-qt + + mkdir -p $out/share/applications + ln -s $out/lib/duckstation/resources/org.duckstation.DuckStation.desktop \ + $out/share/applications + + mkdir -p $out/share/icons/hicolor/512x512/apps + ln -s $out/lib/duckstation/resources/org.duckstation.DuckStation.png \ + $out/share/icons/hicolor/512x512/apps + + pushd .. + install -Dm644 LICENSE -t $out/share/doc/duckstation + install -Dm644 README.* -t $out/share/doc/duckstation + install -Dm644 CONTRIBUTORS.md -t $out/share/doc/duckstation + popd + ''; + + inherit passthru; + + meta = { + inherit (meta) + description + longDescription + homepage + license + maintainers + ; + mainProgram = "duckstation-qt"; + platforms = lib.platforms.linux; + }; + }); + + darwinDrv = stdenvNoCC.mkDerivation (finalAttrs: { + pname = "duckstation-unofficial"; + version = pkgSources.duckstation.version; + + src = fetchurl { + url = "https://github.com/stenzek/duckstation/releases/download/v${finalAttrs.version}/duckstation-mac-release.zip"; + hash = pkgSources.duckstation.hash_darwin; + }; + + nativeBuildInputs = [ unzip ]; + + dontPatch = true; + dontConfigure = true; + dontBuild = true; + + sourceRoot = "."; + + installPhase = '' + runHook preInstall + + mkdir -p $out/Applications + cp -r DuckStation.app $out/Applications/DuckStation.app + + runHook postInstall + ''; + + inherit passthru; + + meta = { + inherit (meta) + description + longDescription + homepage + license + maintainers + ; + sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ]; + platforms = lib.platforms.darwin; + }; + }); +in +if stdenvNoCC.hostPlatform.isLinux then + linuxDrv +else if stdenvNoCC.hostPlatform.isDarwin then + darwinDrv +else + throw "No supported build." diff --git a/pkgs/by-name/du/duckstation-unofficial/sources.json b/pkgs/by-name/du/duckstation-unofficial/sources.json new file mode 100644 index 0000000000000..c51fbc82b0936 --- /dev/null +++ b/pkgs/by-name/du/duckstation-unofficial/sources.json @@ -0,0 +1,20 @@ +{ + "duckstation": { + "version": "0.1-9483", + "hash_linux": "sha256-IKqbZUwm3qvGZKJCxq6t2a6Tc2IXGxZrFLbPE0ZpuMs=", + "hash_darwin": "sha256-68IfUDk9f8Aa/D/MJkWJ48PyMAY143Amx8s63xYeM5Q=" + }, + "discord_rpc": { + "rev": "cc59d26d1d628fbd6527aac0ac1d6301f4978b92", + "hash": "sha256-8xXcx5w36eiJqtWm6qQfhEHgchVJbhP/jR94eMNNjHU=" + }, + "shaderc": { + "rev": "4daf9d466ad00897f755163dd26f528d14e1db44", + "hash": "sha256-/o3LPYvMTlKhuvLQITnADmz8BTGXVaVR0aciOWVyFS8=" + }, + "chtdb": { + "date": "2025-09-07", + "rev": "b29f2919bbd63a2f52d7d3c1c7812fcf88d548d3", + "hash": "sha256-IRgbyiDjUcTZMV+uN/Tdgq4MdF4Uqy9qljAMAGuLG7A=" + } +} diff --git a/pkgs/by-name/du/duckstation-unofficial/update.sh b/pkgs/by-name/du/duckstation-unofficial/update.sh new file mode 100755 index 0000000000000..40ee733bea3b5 --- /dev/null +++ b/pkgs/by-name/du/duckstation-unofficial/update.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash -p curl jq coreutils +# shellcheck shell=bash + +set -euo pipefail +location="$(dirname "${BASH_SOURCE[0]}")" + +echo "checking for new tagged release (github:stenzek/duckstation)..." +old_version=$(nix --extra-experimental-features nix-command eval --raw -f . duckstation-unofficial.src.tag) +new_version=$(curl -s "https://api.github.com/repos/stenzek/duckstation/tags?per_page=1" | jq -r '.[0].name') + +if [[ "$old_version" == "$new_version" ]]; then + echo "'duckstation-unofficial' is up-to-date ($old_version == $new_version)" + exit 0 +fi + +duckstation_linux_hash=$(nix --extra-experimental-features "nix-command flakes" flake prefetch github:stenzek/duckstation/"$new_version" --json | jq -r '.hash') +duckstation_darwin_hash=$(nix-hash --to-sri --type sha256 "$(nix-prefetch-url --type sha256 "https://github.com/stenzek/duckstation/releases/download/${new_version}/duckstation-mac-release.zip")") + + +echo "Vendor library update..." +duckstation_storepath=$(nix flake prefetch github:stenzek/duckstation/"$new_version" --json | jq -r '.storePath') +linux_file=$duckstation_storepath/scripts/deps/build-dependencies-linux.sh + +discord_rpc_rev=$(grep "DISCORD_RPC=" "$linux_file" | sed 's|.*=||g') +discord_rpc_hash=$(nix --extra-experimental-features "nix-command flakes" \ + flake prefetch github:stenzek/discord-rpc/"$discord_rpc_rev" --json \ + | jq -r '.hash') + +shaderc_rev=$(grep "SHADERC=" "$linux_file" | sed 's|.*=||g') +shaderc_hash=$(nix --extra-experimental-features "nix-command flakes" flake prefetch github:stenzek/shaderc/"$shaderc_rev" --json | jq -r '.hash') + +chtdb_json=$(curl -s "https://api.github.com/repos/duckstation/chtdb/commits?per_page=1") +chtdb_rev=$(echo "$chtdb_json" | jq -r '.[0].sha') +chtdb_date=$(echo "$chtdb_json" | jq -r '.[0].commit.author.date') +chtdb_hash=$(nix --extra-experimental-features "nix-command flakes" \ + flake prefetch github:duckstation/chtdb/"$chtdb_rev" --json \ + | jq -r '.hash') + +echo "Regenerating '"$location"/sources.json'" +JSON=$( + jq --null-input \ + --arg new_version "${new_version:1}" \ + --arg duckstation_linux_hash "$duckstation_linux_hash" \ + --arg duckstation_darwin_hash "$duckstation_darwin_hash" \ + --arg discord_rpc_rev "$discord_rpc_rev" \ + --arg discord_rpc_hash "$discord_rpc_hash" \ + --arg shaderc_rev "$shaderc_rev" \ + --arg shaderc_hash "$shaderc_hash" \ + --arg chtdb_rev "$chtdb_rev" \ + --arg chtdb_date "${chtdb_date::10}" \ + --arg chtdb_hash "$chtdb_hash" \ + '{ "duckstation": { + "version": $new_version, + "hash_linux": $duckstation_linux_hash, + "hash_darwin": $duckstation_darwin_hash + }, + "discord_rpc": { + "rev": $discord_rpc_rev, + "hash": $discord_rpc_hash + }, + "shaderc": { + "rev": $shaderc_rev, + "hash": $shaderc_hash + }, + "chtdb": { + "date": $chtdb_date, + "rev": $chtdb_rev, + "hash": $chtdb_hash + } + }' +) + +echo "$JSON" | jq >"$location"/sources.json