3.4 KiB
Bink 2 bridge
Demon's Souls plays Bink 2 (.bk2) files through a Bink implementation linked directly into eboot.bin. It does not use libSceVideodec, therefore an HLE video decoder cannot observe or replace those frames.
By default, SharpEmu leaves Bink decoding to the implementation linked into
the game (SHARPEMU_BINK_MODE=guest).
Set SHARPEMU_BINK_MODE=native to use the optional host bridge. It observes
guest .bk2 opens and presents decoded frames at the guest-flip boundary. The
host path decodes by calling FFmpeg's C API directly from managed
code (src/SharpEmu.Libs/Bink/FfmpegNativeBinkFrameSource.cs, via the
FFmpeg.AutoGen P/Invoke
bindings) against a custom FFmpeg build
(github.com/sharpemu/ffmpeg-core, LGPL-2.1) that adds a Bink 2 decoder to
FFmpeg 7.1.2; see "Supplying the FFmpeg libraries" below for where those
libraries come from. No proprietary RAD SDK is needed to build or run
SharpEmu, and there is no C/C++ code of SharpEmu's own involved in decoding
-- SharpEmu.CLI.csproj only downloads a prebuilt release archive.
Set SHARPEMU_BINK_MODE=skip only when explicitly testing a title whose
cinematics are optional.
Set SHARPEMU_BINK_MODE=dummy to retain the open and show a built-in,
non-decoded placeholder frame. This requires no SDK, but is a visual diagnostic
only; it does not decode the movie or alter its game logic.
SHARPEMU_BINK_MODE=ffmpeg is an alias for native.
Supplying the FFmpeg libraries
Both dotnet build and dotnet publish fetch a prebuilt release of
github.com/sharpemu/ffmpeg-core (the tag is pinned in
SharpEmu.CLI.csproj's FfmpegRuntimeTag, matched to the FFmpeg.AutoGen
package version in Directory.Packages.props -- both need to agree on the
same FFmpeg ABI) and copy its dynamically linked libraries into a plugins
folder next to the resulting executable (artifacts/bin/... for build,
artifacts/publish/... for publish). No C toolchain is required to build
SharpEmu; both just download a zip once (cached under
$(BaseIntermediateOutputPath)ffmpeg-runtime/, so later builds/publishes
reuse it instead of re-fetching). plugins is a loose, unpacked folder
rather than something embedded in the single-file bundle, so the OS loader
can resolve the libraries' own inter-dependencies (avcodec depends on
avutil, etc.) itself.
A plain dotnet build/dotnet publish with no -r still works: it defaults
to the host machine's own RID (see Directory.Build.props), so it fetches
the matching ffmpeg-core archive and populates plugins without any extra
flags. Passing an explicit -r <rid> (e.g. to cross-publish linux-x64 from
Windows) still overrides that default normally.
To use a different set of FFmpeg libraries, drop them into the build or
published plugins folder yourself (matching FFmpeg's own file-naming and versioning
conventions, e.g. avformat-61.dll / libavformat.so.61 / matching
.dylib) -- FfmpegNativeBinkFrameSource points ffmpeg.RootPath at that
folder and does not otherwise care where the files came from.
If the libraries are absent or fail to load, FfmpegNativeBinkFrameSource.TryOpen
degrades gracefully: SharpEmu logs one informational line ("Bink2 bridge
could not open movie ...") and leaves the guest's own rendering path
untouched, rather than crashing.