diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..bd799223 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1722813957, + "narHash": "sha256-IAoYyYnED7P8zrBFMnmp7ydaJfwTnwcnqxUElC1I26Y=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "cb9a96f23c491c081b38eab96d22fa958043c9fa", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..5074a7fb --- /dev/null +++ b/flake.nix @@ -0,0 +1,72 @@ +{ + description = "Nintendo DS emulator"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + inherit (pkgs.lib) cmakeBool optionals makeLibraryPath; + inherit (pkgs.stdenv) isLinux isDarwin; + + versionSuffix = with self; if sourceInfo?dirtyShortRev + then sourceInfo.dirtyShortRev + else sourceInfo.shortRev; + + melonDS = pkgs.stdenv.mkDerivation { + pname = "melonDS"; + version = "0.9.5-${versionSuffix}"; + src = ./.; + + nativeBuildInputs = with pkgs; [ + cmake + ninja + pkg-config + kdePackages.wrapQtAppsHook + ]; + + buildInputs = (with pkgs; [ + kdePackages.qtbase + kdePackages.qtmultimedia + extra-cmake-modules + SDL2 + zstd + libarchive + libGL + libslirp + ]) ++ optionals isLinux [ + pkgs.wayland + pkgs.kdePackages.qtwayland + ]; + + cmakeFlags = [ + (cmakeBool "USE_QT6" true) + (cmakeBool "USE_SYSTEM_LIBSLIRP" true) + ]; + + qtWrapperArgs = optionals isLinux [ + "--prefix LD_LIBRARY_PATH : ${makeLibraryPath [ pkgs.libpcap ]}" + ] ++ optionals isDarwin [ + "--prefix DYLD_LIBRARY_PATH : ${makeLibraryPath [ pkgs.libpcap ]}" + ]; + + passthru = { + exePath = if isDarwin then + "/Applications/melonDS.app/Contents/MacOS/melonDS" + else "/bin/melonDS"; + }; + }; + in { + packages.default = melonDS; + apps.default = flake-utils.lib.mkApp { + drv = self.packages.${system}.default; + }; + devShells.default = pkgs.mkShell { + inputsFrom = [ self.packages.${system}.default ]; + }; + } + ); +} diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index c6301552..656b6535 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -167,9 +167,6 @@ target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../..") target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../../net") -target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../../net/libslirp/src") -get_target_property(SLIRP_BINARY_DIR slirp BINARY_DIR) -target_include_directories(melonDS PUBLIC "${SLIRP_BINARY_DIR}") # for libslirp-version.h if (USE_QT6) target_include_directories(melonDS PUBLIC ${Qt6Gui_PRIVATE_INCLUDE_DIRS}) else() @@ -246,6 +243,8 @@ if (UNIX AND NOT APPLE) INTERPROCEDURAL_OPTIMIZATION OFF INTERPROCEDURAL_OPTIMIZATION_RELEASE OFF) endif() +elseif(APPLE) + install(TARGETS melonDS BUNDLE DESTINATION "${CMAKE_INSTALL_PREFIX}/Applications") endif() if (ENABLE_OGLRENDERER) diff --git a/src/frontend/qt_sdl/Window.cpp b/src/frontend/qt_sdl/Window.cpp index e0b76d19..b59bb770 100644 --- a/src/frontend/qt_sdl/Window.cpp +++ b/src/frontend/qt_sdl/Window.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #ifndef _WIN32 #include #include @@ -366,6 +367,12 @@ MainWindow::MainWindow(int id, EmuInstance* inst, QWidget* parent) : actUndoStateLoad->setShortcut(QKeySequence(Qt::Key_F12)); connect(actUndoStateLoad, &QAction::triggered, this, &MainWindow::onUndoStateLoad); + menu->addSeparator(); + actOpenConfig = menu->addAction("Open melonDS directory"); + connect(actOpenConfig, &QAction::triggered, this, [&]() { + QDesktopServices::openUrl(QUrl::fromLocalFile(emuDirectory)); + }); + menu->addSeparator(); actQuit = menu->addAction("Quit"); diff --git a/src/frontend/qt_sdl/Window.h b/src/frontend/qt_sdl/Window.h index 1dfd680c..30d97b17 100644 --- a/src/frontend/qt_sdl/Window.h +++ b/src/frontend/qt_sdl/Window.h @@ -275,6 +275,7 @@ public: QAction* actSaveState[9]; QAction* actLoadState[9]; QAction* actUndoStateLoad; + QAction* actOpenConfig; QAction* actQuit; QAction* actPause; diff --git a/src/net/CMakeLists.txt b/src/net/CMakeLists.txt index 5116487e..27c8a0ad 100644 --- a/src/net/CMakeLists.txt +++ b/src/net/CMakeLists.txt @@ -1,3 +1,5 @@ +include(FixInterfaceIncludes) + add_library(net-utils STATIC Net.cpp Net_PCap.cpp @@ -16,11 +18,11 @@ target_include_directories(net-utils PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") option(USE_SYSTEM_LIBSLIRP "Use system libslirp instead of the bundled version" OFF) if (USE_SYSTEM_LIBSLIRP) pkg_check_modules(Slirp REQUIRED IMPORTED_TARGET slirp) - target_link_libraries(net-utils PRIVATE PkgConfig::Slirp) + fix_interface_includes(PkgConfig::Slirp) + target_link_libraries(net-utils PUBLIC PkgConfig::Slirp) else() add_subdirectory(libslirp EXCLUDE_FROM_ALL) - target_include_directories(net-utils SYSTEM PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/libslirp/glib") - target_link_libraries(net-utils PRIVATE slirp) + target_link_libraries(net-utils PUBLIC slirp) endif() find_package(ENet REQUIRED) diff --git a/src/net/Net_Slirp.cpp b/src/net/Net_Slirp.cpp index fef4d19c..0386c586 100644 --- a/src/net/Net_Slirp.cpp +++ b/src/net/Net_Slirp.cpp @@ -25,11 +25,6 @@ #include -// "register" is indirectly used by slirp.h but isn't allowed in C++17, this is a workaround -#define register -// Needed for Slirp's definition so we can adjust the opaque pointer in the move constructor -#include - #ifdef __WIN32__ #include #else @@ -163,63 +158,6 @@ Net_Slirp::Net_Slirp(const Platform::SendPacketCallback& callback) noexcept : Ca Ctx = slirp_new(&cfg, &cb, this); } - -Net_Slirp::Net_Slirp(Net_Slirp&& other) noexcept -{ - RXBuffer = other.RXBuffer; - IPv4ID = other.IPv4ID; - Ctx = other.Ctx; - PollListSize = other.PollListSize; - Callback = std::move(other.Callback); - memcpy(PollList, other.PollList, sizeof(PollList)); - - other.RXBuffer = {}; - other.IPv4ID = 0; - other.Ctx = nullptr; - other.PollListSize = 0; - other.Callback = nullptr; - memset(other.PollList, 0, sizeof(other.PollList)); - - if (Ctx) - { - Ctx->opaque = this; - // Gotta ensure that the context doesn't try to pass around a dead object - } -} - -Net_Slirp& Net_Slirp::operator=(Net_Slirp&& other) noexcept -{ - if (this != &other) - { - if (Ctx) - { - slirp_cleanup(Ctx); - } - - RXBuffer = other.RXBuffer; - IPv4ID = other.IPv4ID; - Ctx = other.Ctx; - PollListSize = other.PollListSize; - Callback = std::move(other.Callback); - memcpy(PollList, other.PollList, sizeof(PollList)); - - other.RXBuffer = {}; - other.IPv4ID = 0; - other.Ctx = nullptr; - other.PollListSize = 0; - other.Callback = nullptr; - memset(other.PollList, 0, sizeof(other.PollList)); - - if (Ctx) - { - Ctx->opaque = this; - // Gotta ensure that the context doesn't try to pass around a dead object - } - } - - return *this; -} - Net_Slirp::~Net_Slirp() noexcept { if (Ctx) @@ -229,7 +167,6 @@ Net_Slirp::~Net_Slirp() noexcept } } - void FinishUDPFrame(u8* data, int len) { u8* ipheader = &data[0xE]; diff --git a/src/net/libslirp/CMakeLists.txt b/src/net/libslirp/CMakeLists.txt index 67b8ac78..99d0b3f7 100644 --- a/src/net/libslirp/CMakeLists.txt +++ b/src/net/libslirp/CMakeLists.txt @@ -49,9 +49,9 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/libslirp-version.h.in" "${CMAKE_ add_library(slirp STATIC ${SOURCES}) target_compile_definitions(slirp PUBLIC LIBSLIRP_STATIC_BUILD) -target_include_directories(slirp PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/glib") -target_include_directories(slirp PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src") -target_include_directories(slirp PUBLIC "${CMAKE_CURRENT_BINARY_DIR}") +target_include_directories(slirp SYSTEM PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/glib") +target_include_directories(slirp SYSTEM PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src") +target_include_directories(slirp SYSTEM PUBLIC "${CMAKE_CURRENT_BINARY_DIR}") target_compile_definitions(slirp PRIVATE BUILDING_LIBSLIRP) target_compile_definitions(slirp PRIVATE "G_LOG_DOMAIN=\"Slirp\"") diff --git a/src/net/libslirp/glib/glib.h b/src/net/libslirp/glib/glib.h index e979b12a..3563f7f5 100644 --- a/src/net/libslirp/glib/glib.h +++ b/src/net/libslirp/glib/glib.h @@ -68,10 +68,10 @@ #define GLIB_SIZEOF_VOID_P 8 #ifndef MAX -#define MAX(a, b) (a > b ? a : b) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif #ifndef MIN -#define MIN(a, b) (a < b ? a : b) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif #ifndef TRUE