Skip to content

Commit

Permalink
emulators/duckstation: New port: open-source PlayStation emulator
Browse files Browse the repository at this point in the history
  • Loading branch information
martymac committed Nov 27, 2023
1 parent 96da84a commit c394067
Show file tree
Hide file tree
Showing 11 changed files with 346 additions and 0 deletions.
1 change: 1 addition & 0 deletions emulators/Makefile
Expand Up @@ -25,6 +25,7 @@
SUBDIR += dosbox-staging
SUBDIR += dosbox-x
SUBDIR += dps8m
SUBDIR += duckstation
SUBDIR += dynamips-community
SUBDIR += edumips64
SUBDIR += elliott-803
Expand Down
49 changes: 49 additions & 0 deletions emulators/duckstation/Makefile
@@ -0,0 +1,49 @@
PORTNAME= duckstation
PORTVERSION= 20231016
DISTVERSIONPREFIX= v
CATEGORIES= emulators

MAINTAINER= martymac@FreeBSD.org
COMMENT= Free and open-source PlayStation emulator
WWW= https://www.duckstation.org

LICENSE= GPLv3

LIB_DEPENDS= libcurl.so:ftp/curl \
libbacktrace.so:devel/libbacktrace \
libxkbcommon.so:x11/libxkbcommon \
libpulse.so:audio/pulseaudio \
libjack.so:audio/jack \
libsndio.so:audio/sndio \
libdbus-1.so:devel/dbus
# XXX Necessary for Qt6/FindWrapVulkanHeaders.cmake
BUILD_DEPENDS= vulkan-headers>0:graphics/vulkan-headers

USES= cmake compiler:c++20-lang gl pkgconfig qt:6 sdl xorg

USE_GITHUB= yes
GH_ACCOUNT= stenzek
# See: https://github.com/stenzek/duckstation/releases/tag/latest
GH_TAGNAME= cecae91

USE_GL= egl
USE_SDL= sdl2
USE_XORG= ice x11 xext xrandr xrender
USE_QT= base tools

CMAKE_ARGS+= \
-DDUCKSTATION_APPLICATION_DIR_PATH:STRING=${DATADIR}

# - Program and resources are copied from target dir ${CONFIGURE_WRKSRC}/bin
# because only necessary resources are installed there
do-install:
cd ${CONFIGURE_WRKSRC}/bin && \
${COPYTREE_SHARE} resources/ ${STAGEDIR}${DATADIR}/ && \
${COPYTREE_SHARE} translations/ ${STAGEDIR}${DATADIR}/
${INSTALL_PROGRAM} \
${CONFIGURE_WRKSRC}/bin/duckstation-qt ${STAGEDIR}${PREFIX}/bin/
${INSTALL_DATA} ${CONFIGURE_WRKSRC}/bin/resources/images/duck.png \
${STAGEDIR}${PREFIX}/share/pixmaps/duckstation.png
${INSTALL_DATA} ${FILESDIR}/duckstation.desktop ${STAGEDIR}${DESKTOPDIR}

.include <bsd.port.mk>
3 changes: 3 additions & 0 deletions emulators/duckstation/distinfo
@@ -0,0 +1,3 @@
TIMESTAMP = 1700156894
SHA256 (stenzek-duckstation-v20231016-cecae91_GH0.tar.gz) = e1c25940db1b517b5dfbf73d7f21a584194ddd0d6a93f11b45210a021d4841c7
SIZE (stenzek-duckstation-v20231016-cecae91_GH0.tar.gz) = 13424608
12 changes: 12 additions & 0 deletions emulators/duckstation/files/duckstation.desktop
@@ -0,0 +1,12 @@
[Desktop Entry]
Version=1.0
Terminal=false
Type=Application
Name=Duckstation
StartupWMClass=Duckstation
GenericName=PlayStation Emulator
Comment=Sony PlayStation emulator
Exec=duckstation-qt
Icon=duckstation
Keywords=game;emulator;
Categories=Game;Emulator;
24 changes: 24 additions & 0 deletions emulators/duckstation/files/patch-data-directory.txt
@@ -0,0 +1,24 @@
Fix data directory handling on FreeBSD

--- src/duckstation-qt/qthost.cpp.orig 2023-10-16 12:57:57 UTC
+++ src/duckstation-qt/qthost.cpp
@@ -289,7 +289,7 @@ void QtHost::SetDataDirectory()
EmuFolders::DataRoot = Path::Combine(StringUtil::WideStringToUTF8String(documents_directory), "DuckStation");
CoTaskMemFree(documents_directory);
}
-#elif defined(__linux__)
+#elif defined(__linux__) || defined(__FreeBSD__)
// Use $XDG_CONFIG_HOME/duckstation if it exists.
const char* xdg_config_home = getenv("XDG_CONFIG_HOME");
if (xdg_config_home && Path::IsAbsolute(xdg_config_home))
--- src/duckstation-nogui/nogui_host.cpp.orig 2023-10-16 12:57:57 UTC
+++ src/duckstation-nogui/nogui_host.cpp
@@ -186,7 +186,7 @@ void NoGUIHost::SetDataDirectory()
EmuFolders::DataRoot = Path::Combine(StringUtil::WideStringToUTF8String(documents_directory), "DuckStation");
CoTaskMemFree(documents_directory);
}
-#elif defined(__linux__)
+#elif defined(__linux__) || defined(__FreeBSD__)
// Use $XDG_CONFIG_HOME/duckstation if it exists.
const char* xdg_config_home = getenv("XDG_CONFIG_HOME");
if (xdg_config_home && Path::IsAbsolute(xdg_config_home))
74 changes: 74 additions & 0 deletions emulators/duckstation/files/patch-relocate-resources.txt
@@ -0,0 +1,74 @@
Allow relocation of resource files and translations

--- CMakeLists.txt.orig 2023-10-16 12:57:57 UTC
+++ CMakeLists.txt
@@ -44,6 +44,9 @@ endif()
endif()
endif()

+if(DEFINED DUCKSTATION_APPLICATION_DIR_PATH)
+ add_compile_definitions(DUCKSTATION_APPLICATION_DIR_PATH="${DUCKSTATION_APPLICATION_DIR_PATH}")
+endif()

# Required libraries.
if(ENABLE_SDL2)
--- src/duckstation-qt/qthost.cpp.orig 2023-11-20 14:04:38 UTC
+++ src/duckstation-qt/qthost.cpp
@@ -259,6 +259,10 @@ void QtHost::SetResourcesDirectory()

void QtHost::SetResourcesDirectory()
{
+#ifdef DUCKSTATION_APPLICATION_DIR_PATH
+ // Resources' path specified at compile time
+ EmuFolders::Resources = Path::Canonicalize(DUCKSTATION_APPLICATION_DIR_PATH "/resources");
+#else
#ifndef __APPLE__
// On Windows/Linux, these are in the binary directory.
EmuFolders::Resources = Path::Combine(EmuFolders::AppRoot, "resources");
@@ -266,6 +270,7 @@ void QtHost::SetResourcesDirectory()
// On macOS, this is in the bundle resources directory.
EmuFolders::Resources = Path::Canonicalize(Path::Combine(EmuFolders::AppRoot, "../Resources"));
#endif
+#endif // DUCKSTATION_APPLICATION_DIR_PATH
}

void QtHost::SetDataDirectory()
--- src/duckstation-nogui/nogui_host.cpp.orig 2023-10-16 12:57:57 UTC
+++ src/duckstation-nogui/nogui_host.cpp
@@ -156,6 +156,10 @@ void NoGUIHost::SetResourcesDirectory()

void NoGUIHost::SetResourcesDirectory()
{
+#ifdef DUCKSTATION_APPLICATION_DIR_PATH
+ // Resources' path specified at compile time
+ EmuFolders::Resources = Path::Canonicalize(DUCKSTATION_APPLICATION_DIR_PATH "/resources");
+#else
#ifndef __APPLE__NOT_USED // Not using bundles yet.
// On Windows/Linux, these are in the binary directory.
EmuFolders::Resources = Path::Combine(EmuFolders::AppRoot, "resources");
@@ -163,6 +167,7 @@ void NoGUIHost::SetResourcesDirectory()
// On macOS, this is in the bundle resources directory.
EmuFolders::Resources = Path::Canonicalize(Path::Combine(EmuFolders::AppRoot, "../Resources"));
#endif
+#endif // DUCKSTATION_APPLICATION_DIR_PATH
}

void NoGUIHost::SetDataDirectory()
--- src/duckstation-qt/qttranslations.cpp.orig 2023-10-16 12:57:57 UTC
+++ src/duckstation-qt/qttranslations.cpp
@@ -73,11 +73,15 @@ void QtHost::InstallTranslator()
FixLanguageName(QString::fromStdString(Host::GetBaseStringSettingValue("Main", "Language", GetDefaultLanguage())));

// install the base qt translation first
+#ifdef DUCKSTATION_APPLICATION_DIR_PATH
+ const QString base_dir = QStringLiteral(DUCKSTATION_APPLICATION_DIR_PATH "/translations");
+#else
#ifndef __APPLE__
const QString base_dir = QStringLiteral("%1/translations").arg(qApp->applicationDirPath());
#else
const QString base_dir = QStringLiteral("%1/../Resources/translations").arg(qApp->applicationDirPath());
#endif
+#endif // DUCKSTATION_APPLICATION_DIR_PATH

// Qt base uses underscores instead of hyphens.
const QString qt_language = QString(language).replace(QChar('-'), QChar('_'));
14 changes: 14 additions & 0 deletions emulators/duckstation/files/patch-src-common-byte_stream.cpp
@@ -0,0 +1,14 @@
FreeBSD's alloca(3) only needs <stdlib.h>
--- src/common/byte_stream.cpp.orig 2023-10-16 12:57:57 UTC
+++ src/common/byte_stream.cpp
@@ -28,7 +28,9 @@
#ifdef _MSC_VER
#include <malloc.h>
#else
+#if !defined(__FreeBSD__)
#include <alloca.h>
+#endif
#endif
Log_SetChannel(ByteStream);
70 changes: 70 additions & 0 deletions emulators/duckstation/files/patch-src-common-file_system.cpp
@@ -0,0 +1,70 @@
Fix an off-by-one '..' error when computing bios SearchPath

A '..' is missing in returned path when 'path' and 'relative_to' have no common
components. C++17's std::filesystem::relative() method returns a correct value.

As an alternative to that simple patch, we may want to just replace
Path::MakeRelative() calls by std::filesystem::relative() calls and remove
Path::MakeRelative() method.

--- src/common/file_system.cpp.orig 2023-10-16 12:57:57 UTC
+++ src/common/file_system.cpp
@@ -12,6 +12,7 @@
#include <cstdlib>
#include <cstring>
#include <limits>
+#include <filesystem>

#ifdef __APPLE__
#include <mach-o/dyld.h>
@@ -250,49 +251,7 @@ std::string Path::MakeRelative(const std::string_view&

std::string Path::MakeRelative(const std::string_view& path, const std::string_view& relative_to)
{
- // simple algorithm, we just work on the components. could probably be better, but it'll do for now.
- std::vector<std::string_view> path_components(SplitNativePath(path));
- std::vector<std::string_view> relative_components(SplitNativePath(relative_to));
- std::vector<std::string_view> new_components;
-
- // both must be absolute paths
- if (Path::IsAbsolute(path) && Path::IsAbsolute(relative_to))
- {
- // find the number of same components
- size_t num_same = 0;
- for (size_t i = 0; i < path_components.size() && i < relative_components.size(); i++)
- {
- if (path_components[i] == relative_components[i])
- num_same++;
- else
- break;
- }
-
- // we need at least one same component
- if (num_same > 0)
- {
- // from the relative_to directory, back up to the start of the common components
- const size_t num_ups = relative_components.size() - num_same;
- for (size_t i = 0; i < num_ups; i++)
- new_components.emplace_back("..");
-
- // and add the remainder of the path components
- for (size_t i = num_same; i < path_components.size(); i++)
- new_components.push_back(std::move(path_components[i]));
- }
- else
- {
- // no similarity
- new_components = std::move(path_components);
- }
- }
- else
- {
- // not absolute
- new_components = std::move(path_components);
- }
-
- return JoinNativePath(new_components);
+ return std::filesystem::relative(path, relative_to);
}

std::string_view Path::GetExtension(const std::string_view& path)
22 changes: 22 additions & 0 deletions emulators/duckstation/files/patch-src-common-threading.cpp
@@ -0,0 +1,22 @@
Fix get_thread_time() declaration on FreeBSD

--- src/common/threading.cpp.orig 2023-10-16 12:57:57 UTC
+++ src/common/threading.cpp
@@ -64,7 +64,7 @@ static u64 getthreadtime(thread_port_t thread)
}
#endif

-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD__)
// Helper function to get either either the current cpu usage
// in called thread or in id thread
static u64 get_thread_time(void* id = 0)
@@ -227,7 +227,7 @@ u64 Threading::ThreadHandle::GetCPUTime() const
return user.u64time + kernel.u64time;
#elif defined(__APPLE__)
return getthreadtime(pthread_mach_thread_np((pthread_t)m_native_handle));
-#elif defined(__linux__)
+#elif defined(__linux__) || defined(__FreeBSD__)
return get_thread_time(m_native_handle);
#else
return 0;
6 changes: 6 additions & 0 deletions emulators/duckstation/pkg-descr
@@ -0,0 +1,6 @@
DuckStation is a PlayStation 1, aka. PSX Emulator.

DuckStation is an simulator/emulator of the Sony PlayStation(TM) console,
focusing on playability, speed, and long-term maintainability. The goal is to
be as accurate as possible while maintaining performance suitable for low-end
devices.
71 changes: 71 additions & 0 deletions emulators/duckstation/pkg-plist
@@ -0,0 +1,71 @@
bin/duckstation-qt
share/applications/duckstation.desktop
share/pixmaps/duckstation.png
%%DATADIR%%/resources/chtdb.txt
%%DATADIR%%/resources/fonts/LICENSE.txt
%%DATADIR%%/resources/fonts/Roboto-Regular.ttf
%%DATADIR%%/resources/fonts/RobotoMono-Medium.ttf
%%DATADIR%%/resources/fonts/fa-solid-900.ttf
%%DATADIR%%/resources/fullscreenui/NTSC-J.png
%%DATADIR%%/resources/fullscreenui/NTSC-U.png
%%DATADIR%%/resources/fullscreenui/PAL.png
%%DATADIR%%/resources/fullscreenui/address-book-new.png
%%DATADIR%%/resources/fullscreenui/applications-system.png
%%DATADIR%%/resources/fullscreenui/media-cdrom.png
%%DATADIR%%/resources/fullscreenui/multimedia-player.png
%%DATADIR%%/resources/fullscreenui/star-0.png
%%DATADIR%%/resources/fullscreenui/star-1.png
%%DATADIR%%/resources/fullscreenui/star-2.png
%%DATADIR%%/resources/fullscreenui/star-3.png
%%DATADIR%%/resources/fullscreenui/star-4.png
%%DATADIR%%/resources/fullscreenui/star-5.png
%%DATADIR%%/resources/gamecontrollerdb.txt
%%DATADIR%%/resources/gamedb.json
%%DATADIR%%/resources/images/cover-placeholder.png
%%DATADIR%%/resources/images/crosshair.png
%%DATADIR%%/resources/images/duck.png
%%DATADIR%%/resources/images/placeholder.png
%%DATADIR%%/resources/images/sources.txt
%%DATADIR%%/resources/shaders/Cccalibrator.glsl
%%DATADIR%%/resources/shaders/crt-lottes.glsl
%%DATADIR%%/resources/shaders/dolphinfx/bloom.glsl
%%DATADIR%%/resources/shaders/dolphinfx/celshading.glsl
%%DATADIR%%/resources/shaders/dolphinfx/scanlines.glsl
%%DATADIR%%/resources/shaders/reshade/README.md
%%DATADIR%%/resources/shaders/reshade/REFERENCE.md
%%DATADIR%%/resources/shaders/reshade/Shaders/Blending.fxh
%%DATADIR%%/resources/shaders/reshade/Shaders/Daltonize.fx
%%DATADIR%%/resources/shaders/reshade/Shaders/Deband.fx
%%DATADIR%%/resources/shaders/reshade/Shaders/DrawText.fxh
%%DATADIR%%/resources/shaders/reshade/Shaders/LUT.fx
%%DATADIR%%/resources/shaders/reshade/Shaders/Macros.fxh
%%DATADIR%%/resources/shaders/reshade/Shaders/ReShade.fxh
%%DATADIR%%/resources/shaders/reshade/Shaders/ReShadeUI.fxh
%%DATADIR%%/resources/shaders/reshade/Shaders/TriDither.fxh
%%DATADIR%%/resources/shaders/reshade/Textures/FontAtlas.png
%%DATADIR%%/resources/shaders/reshade/Textures/lut.png
%%DATADIR%%/resources/shaders/reshade/source.txt
%%DATADIR%%/resources/shaders/simple-brightness.glsl
%%DATADIR%%/resources/shaders/simple-flip.glsl
%%DATADIR%%/resources/shaders/simple-gamma.glsl
%%DATADIR%%/resources/shaders/simple-sharpen.glsl
%%DATADIR%%/resources/sounds/achievements/README.txt
%%DATADIR%%/resources/sounds/achievements/lbsubmit.wav
%%DATADIR%%/resources/sounds/achievements/message.wav
%%DATADIR%%/resources/sounds/achievements/unlock.wav
%%DATADIR%%/translations/duckstation-qt_de.qm
%%DATADIR%%/translations/duckstation-qt_en.qm
%%DATADIR%%/translations/duckstation-qt_es-ES.qm
%%DATADIR%%/translations/duckstation-qt_es.qm
%%DATADIR%%/translations/duckstation-qt_fr.qm
%%DATADIR%%/translations/duckstation-qt_he.qm
%%DATADIR%%/translations/duckstation-qt_it.qm
%%DATADIR%%/translations/duckstation-qt_ja.qm
%%DATADIR%%/translations/duckstation-qt_ko.qm
%%DATADIR%%/translations/duckstation-qt_nl.qm
%%DATADIR%%/translations/duckstation-qt_pl.qm
%%DATADIR%%/translations/duckstation-qt_pt-BR.qm
%%DATADIR%%/translations/duckstation-qt_pt-PT.qm
%%DATADIR%%/translations/duckstation-qt_ru.qm
%%DATADIR%%/translations/duckstation-qt_tr.qm
%%DATADIR%%/translations/duckstation-qt_zh-CN.qm

0 comments on commit c394067

Please sign in to comment.