Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 177 additions & 0 deletions pkgs/applications/emulators/yuzu/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
{
callPackage,
fetchFromGitLab,
fetchpatch,
fetchFromGitea,
fmt_11,
fetchzip,
git,
dos2unix,
sdl3,
}:

{
torzu = callPackage ./generic.nix {
forkName = "torzu";
version = "unstable-2024-02-26";
source = fetchFromGitea {
domain = "git.ynh.ovh";
owner = "liberodark";
repo = "torzu";
rev = "eaa9c9e3a46eb5099193b11d620ddfe96b6aec83";
hash = "sha256-KxLRXM8Y+sIW5L9oYMSeK95HRb30zGRRSfil9DO+utU=";
fetchSubmodules = true;
};
patches = [
# Remove coroutines from debugger to fix boost::asio compatibility issues
./fix-debugger.patch
# Add explicit cast for CRC checksum value
./fix-udp-protocol.patch
# Use specific boost::asio includes and update to modern io_context
./fix-udp-client.patch
# Updates suppressed diagnostics
./fix-aarch64-linux-build.patch
];
homepage = "http://vub63vv26q6v27xzv2dtcd25xumubshogm67yrpaz2rculqxs7jlfqad.onion/torzu-emu/torzu";
};

citron-emu = callPackage ./generic.nix (
let
version = "0.6.1";
in
{
forkName = "citron";
inherit version;
source = fetchFromGitLab {
domain = "git.citron-emu.org";
owner = "citron";
repo = "emu";
rev = "v${version}-canary-refresh";
hash = "sha256-ZQ6k/9e1ZwUXqc5h3dnza27LtpUtQY4eUjeMtX3+in8=";
# Submodules are fixed in master until a new tag is out apply fix manually
leaveDotGit = true;
nativeBuildInputs = [
git
dos2unix
];
postFetch = ''
pushd $out
# Git won't allow working on submodules otherwise...
git restore --staged .

cp .gitmodules{,.bak}

substituteInPlace .gitmodules \
--replace-fail git.citron-emu.org/Citron github.com/yuzu-mirror

git submodule update --init --recursive -j ''${NIX_BUILD_CORES:-1} --progress --depth 1 --checkout --force

mv .gitmodules{.bak,}

# Remove .git dirs
find . -name .git -type f -exec rm -rf {} +
rm -rf .git/
popd
'';
};
patches = [
# Add explicit cast for CRC checksum value
./fix-udp-protocol.patch
# Use specific boost::asio includes and update to modern io_context
(fetchpatch {
url = "https://git.citron-emu.org/citron/emu/-/commit/21ca0b31191c4af56a78576c502e8382b4c128b4.patch";
hash = "sha256-DkCGjeNYjCA7RdB+hBRXuHL8Ckjb+IgWbZ13leQZUF0=";
})
];
cmakeFlagsPrefix = "CITRON";
udevFileName = "72-citron-input.rules";
fmt = fmt_11;
homepage = "https://git.citron-emu.org/citron/emu/-/releases";
mainProgram = "citron";
}
);

sudachi = callPackage ./generic.nix (
let
version = "1.0.15";
in
{
forkName = "sudachi";
inherit version;
source = fetchzip {
url = "https://github.com/emuplace/sudachi.emuplace.app/releases/download/v${version}/latest.zip";
hash = "sha256-9qfDtuJWE4KpCY7RFXw/VdYOR0bNe+80afO7/FJ+Cog=";
stripRoot = false;
nativeBuildInputs = [
git
dos2unix
];
postFetch = ''
pushd $out
# Patches will fail to apply because of line endings
find . -type f -print0 | xargs -0 dos2unix

# Restore submodules from .gitmodules file
# https://stackoverflow.com/a/11258810
git init
git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
while read path_key local_path
do
url_key=$(echo $path_key | sed 's/\.path/.url/')
url=$(git config -f .gitmodules --get "$url_key")
rmdir $local_path
git submodule add $url $local_path
done
# Fetch nested submodules
git submodule update --init --recursive

# Fix submodules versions
(cd externals/cpp-jwt && git checkout 4a970bc302d671476122cbc6b43cc89fbf4a96ec)

# Remove .git dirs
find . -name .git -type f -exec rm -rf {} +
rm -rf .git/
'';
};
patches = [
# Add explicit cast for CRC checksum value
./fix-udp-protocol.patch
# Updates suppressed diagnostics
./fix-aarch64-linux-build.patch
# Revert imports to codec.h
./fix-libavcodec-import.patch
# Revert libav function usage
./fix-libavcodec-function.patch
# Fix code mistakes
# from https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=sudachi
./fix-sudachi-window.patch
./fix-sudachi-guest-memory-namespace.patch
];
cmakeFlagsPrefix = "SUDACHI";
udevFileName = "72-sudachi-input.rules";
SDL2 = sdl3;
homepage = "https://sudachi.emuplace.app/";
mainProgram = "sudachi";
}
);

eden = callPackage ./generic.nix (
let
version = "0.0.2";
in
{
forkName = "eden";
inherit version;
source = fetchFromGitea {
domain = "git.eden-emu.dev";
owner = "eden-emu";
repo = "eden";
rev = "${version}-pre-alpha";
hash = "sha256-bf4QF0POVD8siviDxp3n4ZspRm8ETkmAx0WVrg2nyYI=";
fetchSubmodules = true;
};
homepage = "https://git.eden-emu.dev/eden-emu/eden/releases";
mainProgram = "eden";
}
);
}
183 changes: 183 additions & 0 deletions pkgs/applications/emulators/yuzu/fix-libavcodec-function.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
--- a/src/video_core/host1x/ffmpeg/ffmpeg.cpp
+++ b/src/video_core/host1x/ffmpeg/ffmpeg.cpp
@@ -218,6 +218,165 @@
return true;
}

+// Nasty but allows linux builds to pass.
+// Requires double checks when FFMPEG gets updated.
+// Hopefully a future FFMPEG update will all and expose a solution in the public API.
+namespace {
+
+typedef struct FFCodecDefault {
+ const char* key;
+ const char* value;
+} FFCodecDefault;
+
+typedef struct FFCodec {
+ /**
+ * The public AVCodec. See codec.h for it.
+ */
+ AVCodec p;
+
+ /**
+ * Internal codec capabilities FF_CODEC_CAP_*.
+ */
+ unsigned caps_internal : 29;
+
+ /**
+ * This field determines the type of the codec (decoder/encoder)
+ * and also the exact callback cb implemented by the codec.
+ * cb_type uses enum FFCodecType values.
+ */
+ unsigned cb_type : 3;
+
+ int priv_data_size;
+ /**
+ * @name Frame-level threading support functions
+ * @{
+ */
+ /**
+ * Copy necessary context variables from a previous thread context to the current one.
+ * If not defined, the next thread will start automatically; otherwise, the codec
+ * must call ff_thread_finish_setup().
+ *
+ * dst and src will (rarely) point to the same context, in which case memcpy should be skipped.
+ */
+ int (*update_thread_context)(struct AVCodecContext* dst, const struct AVCodecContext* src);
+
+ /**
+ * Copy variables back to the user-facing context
+ */
+ int (*update_thread_context_for_user)(struct AVCodecContext* dst,
+ const struct AVCodecContext* src);
+ /** @} */
+
+ /**
+ * Private codec-specific defaults.
+ */
+ const FFCodecDefault* defaults;
+
+ /**
+ * Initialize codec static data, called from av_codec_iterate().
+ *
+ * This is not intended for time consuming operations as it is
+ * run for every codec regardless of that codec being used.
+ */
+ void (*init_static_data)(struct FFCodec* codec);
+
+ int (*init)(struct AVCodecContext*);
+
+ union {
+ /**
+ * Decode to an AVFrame.
+ * cb is in this state if cb_type is FF_CODEC_CB_TYPE_DECODE.
+ *
+ * @param avctx codec context
+ * @param[out] frame AVFrame for output
+ * @param[out] got_frame_ptr decoder sets to 0 or 1 to indicate that
+ * a non-empty frame was returned in frame.
+ * @param[in] avpkt AVPacket containing the data to be decoded
+ * @return amount of bytes read from the packet on success,
+ * negative error code on failure
+ */
+ int (*decode)(struct AVCodecContext* avctx, struct AVFrame* frame, int* got_frame_ptr,
+ struct AVPacket* avpkt);
+ /**
+ * Decode subtitle data to an AVSubtitle.
+ * cb is in this state if cb_type is FF_CODEC_CB_TYPE_DECODE_SUB.
+ *
+ * Apart from that this is like the decode callback.
+ */
+ int (*decode_sub)(struct AVCodecContext* avctx, struct AVSubtitle* sub, int* got_frame_ptr,
+ const struct AVPacket* avpkt);
+ /**
+ * Decode API with decoupled packet/frame dataflow.
+ * cb is in this state if cb_type is FF_CODEC_CB_TYPE_RECEIVE_FRAME.
+ *
+ * This function is called to get one output frame. It should call
+ * ff_decode_get_packet() to obtain input data.
+ */
+ int (*receive_frame)(struct AVCodecContext* avctx, struct AVFrame* frame);
+ /**
+ * Encode data to an AVPacket.
+ * cb is in this state if cb_type is FF_CODEC_CB_TYPE_ENCODE
+ *
+ * @param avctx codec context
+ * @param[out] avpkt output AVPacket
+ * @param[in] frame AVFrame containing the input to be encoded
+ * @param[out] got_packet_ptr encoder sets to 0 or 1 to indicate that a
+ * non-empty packet was returned in avpkt.
+ * @return 0 on success, negative error code on failure
+ */
+ int (*encode)(struct AVCodecContext* avctx, struct AVPacket* avpkt,
+ const struct AVFrame* frame, int* got_packet_ptr);
+ /**
+ * Encode subtitles to a raw buffer.
+ * cb is in this state if cb_type is FF_CODEC_CB_TYPE_ENCODE_SUB.
+ */
+ int (*encode_sub)(struct AVCodecContext* avctx, uint8_t* buf, int buf_size,
+ const struct AVSubtitle* sub);
+ /**
+ * Encode API with decoupled frame/packet dataflow.
+ * cb is in this state if cb_type is FF_CODEC_CB_TYPE_RECEIVE_PACKET.
+ *
+ * This function is called to get one output packet.
+ * It should call ff_encode_get_frame() to obtain input data.
+ */
+ int (*receive_packet)(struct AVCodecContext* avctx, struct AVPacket* avpkt);
+ } cb;
+
+ int (*close)(struct AVCodecContext*);
+
+ /**
+ * Flush buffers.
+ * Will be called when seeking
+ */
+ void (*flush)(struct AVCodecContext*);
+
+ /**
+ * Decoding only, a comma-separated list of bitstream filters to apply to
+ * packets before decoding.
+ */
+ const char* bsfs;
+
+ /**
+ * Array of pointers to hardware configurations supported by the codec,
+ * or NULL if no hardware supported. The array is terminated by a NULL
+ * pointer.
+ *
+ * The user can only access this field via avcodec_get_hw_config().
+ */
+ const struct AVCodecHWConfigInternal* const* hw_configs;
+
+ /**
+ * List of supported codec_tags, terminated by FF_CODEC_TAGS_END.
+ */
+ const uint32_t* codec_tags;
+} FFCodec;
+
+static av_always_inline const FFCodec* ffcodec(const AVCodec* codec) {
+ return (const FFCodec*)codec;
+}
+
+} // namespace
+
bool DecoderContext::SendPacket(const Packet& packet) {
m_temp_frame = std::make_shared<Frame>();
m_got_frame = 0;
@@ -306,12 +465,8 @@
}

#if defined(FF_API_INTERLACED_FRAME) || LIBAVUTIL_VERSION_MAJOR >= 59
- if (m_temp_frame->GetFrame()->flags & AV_FRAME_FLAG_INTERLACED)
- m_temp_frame->GetFrame()->flags &= ~AV_FRAME_FLAG_INTERLACED;
- else
- m_temp_frame->GetFrame()->flags |= AV_FRAME_FLAG_INTERLACED;
-#else
- m_temp_frame->GetFrame()->interlaced_frame = !m_temp_frame->GetFrame()->interlaced_frame;
+ m_temp_frame->GetFrame()->interlaced_frame =
+ (m_temp_frame->GetFrame()->flags & AV_FRAME_FLAG_INTERLACED) != 0;
#endif
return std::move(m_temp_frame);
}
11 changes: 11 additions & 0 deletions pkgs/applications/emulators/yuzu/fix-libavcodec-import.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--- a/src/video_core/host1x/ffmpeg/ffmpeg.h
+++ b/src/video_core/host1x/ffmpeg/ffmpeg.h
@@ -22,7 +22,7 @@
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
#ifndef ANDROID
-#include <libavcodec/codec_internal.h>
+#include <libavcodec/codec.h>
#endif

#if defined(__GNUC__) || defined(__clang__)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--- a/src/core/guest_memory.h
+++ b/src/core/guest_memory.h
@@ -31,7 +31,6 @@
UnsafeReadCachedWrite = UnsafeReadWrite | Cached,
};

-namespace {
template <typename M, typename T, GuestMemoryFlags FLAGS>
class GuestMemory {
using iterator = T*;
@@ -221,4 +220,3 @@
};
} // namespace

-} // namespace Core::Memory
Loading