diff options
author | Arisotura <thetotalworm@gmail.com> | 2020-06-04 02:13:16 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-04 02:13:16 +0200 |
commit | 90cf310e8114a9bf813b764d4f501e1f3133e77f (patch) | |
tree | bf04bfb2892a394c27b83758d28fec2462362e0c /src/frontend/qt_sdl | |
parent | 1abcb4e6ac65e31a0d76d457524e9aeade8419ee (diff) | |
parent | 924975f6db7acc419f3ed1758fc5705ea1b13aea (diff) |
Merge pull request #641 from nadiaholmquist/feature/qt-platform
Use Qt's file/threading abstractions in Platform.cpp
Diffstat (limited to 'src/frontend/qt_sdl')
-rw-r--r-- | src/frontend/qt_sdl/CMakeLists.txt | 120 | ||||
-rw-r--r-- | src/frontend/qt_sdl/Platform.cpp | 428 |
2 files changed, 171 insertions, 377 deletions
diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 62d6e60..ea7849f 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -1,41 +1,41 @@ project(qt_sdl) SET(SOURCES_QT_SDL - main.cpp - main_shaders.h - EmuSettingsDialog.cpp - InputConfigDialog.cpp - VideoSettingsDialog.cpp - AudioSettingsDialog.cpp - WifiSettingsDialog.cpp - Input.cpp - LAN_PCap.cpp - LAN_Socket.cpp - OSD.cpp - OSD_shaders.h - font.h - Platform.cpp - PlatformConfig.cpp - - ../Util_ROM.cpp - ../Util_Video.cpp - ../Util_Audio.cpp - ../FrontendUtil.h - ../mic_blow.h - - ../../../melon.qrc + main.cpp + main_shaders.h + EmuSettingsDialog.cpp + InputConfigDialog.cpp + VideoSettingsDialog.cpp + AudioSettingsDialog.cpp + WifiSettingsDialog.cpp + Input.cpp + LAN_PCap.cpp + LAN_Socket.cpp + OSD.cpp + OSD_shaders.h + font.h + Platform.cpp + PlatformConfig.cpp + + ../Util_ROM.cpp + ../Util_Video.cpp + ../Util_Audio.cpp + ../FrontendUtil.h + ../mic_blow.h + + ../../../melon.qrc ) if (WIN32) - set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> -i <SOURCE> -o <OBJECT>") + set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> -i <SOURCE> -o <OBJECT>") endif() if (BUILD_STATIC AND QT5_STATIC_DIR) - set(QT5_STATIC_BASE ${QT5_STATIC_DIR}/lib/cmake/Qt5) - set(Qt5_DIR ${QT5_STATIC_BASE}) - set(Qt5Core_DIR ${QT5_STATIC_BASE}Core) - set(Qt5Gui_DIR ${QT5_STATIC_BASE}Gui) - set(Qt5Widgets_DIR ${QT5_STATIC_BASE}Widgets) + set(QT5_STATIC_BASE ${QT5_STATIC_DIR}/lib/cmake/Qt5) + set(Qt5_DIR ${QT5_STATIC_BASE}) + set(Qt5Core_DIR ${QT5_STATIC_BASE}Core) + set(Qt5Gui_DIR ${QT5_STATIC_BASE}Gui) + set(Qt5Widgets_DIR ${QT5_STATIC_BASE}Widgets) endif() find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED) @@ -44,15 +44,18 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) +find_package(Threads REQUIRED) find_package(PkgConfig REQUIRED) pkg_check_modules(SDL2 REQUIRED sdl2) if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL Release)) - add_executable(melonDS WIN32 ${SOURCES_QT_SDL}) + add_executable(melonDS WIN32 ${SOURCES_QT_SDL}) else() - add_executable(melonDS ${SOURCES_QT_SDL}) + add_executable(melonDS ${SOURCES_QT_SDL}) endif() +target_link_libraries(melonDS ${CMAKE_THREAD_LIBS_INIT}) + target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS}) target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") @@ -60,48 +63,29 @@ target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../..") target_link_libraries(melonDS core) if (BUILD_STATIC) - target_link_libraries(melonDS -static ${SDL2_LIBRARIES}) + target_link_libraries(melonDS -static ${SDL2_LIBRARIES}) else() - target_link_libraries(melonDS ${SDL2_LIBRARIES}) + target_link_libraries(melonDS ${SDL2_LIBRARIES}) endif() if (UNIX) - option(UNIX_PORTABLE "Make a portable build that looks for its configuration in the current directory" OFF) - if (UNIX_PORTABLE) - add_definitions(-DUNIX_PORTABLE) - endif() - - find_package(PkgConfig REQUIRED) - pkg_check_modules(GTK3 REQUIRED gtk+-3.0) - - target_include_directories(melonDS PRIVATE ${GTK3_INCLUDE_DIRS}) - target_link_libraries(melonDS ${GTK3_LIBRARIES}) - - ADD_DEFINITIONS(${GTK3_CFLAGS_OTHER}) - - add_custom_command(OUTPUT melon_grc.c - COMMAND glib-compile-resources --sourcedir=${CMAKE_SOURCE_DIR} - --target=${CMAKE_CURRENT_BINARY_DIR}/melon_grc.c - --generate-source "${CMAKE_SOURCE_DIR}/melon_grc.xml" - COMMAND glib-compile-resources --sourcedir=${CMAKE_SOURCE_DIR} - --target=${CMAKE_CURRENT_BINARY_DIR}/melon_grc.h - --generate-header "${CMAKE_SOURCE_DIR}/melon_grc.xml") - - if (CMAKE_SYSTEM_NAME STREQUAL "Linux") - target_link_libraries(melonDS dl Qt5::Core Qt5::Gui Qt5::Widgets) - endif () - - target_sources(melonDS PUBLIC melon_grc.c) + option(PORTABLE "Make a portable build that looks for its configuration in the current directory" OFF) + target_link_libraries(melonDS dl Qt5::Core Qt5::Gui Qt5::Widgets) elseif (WIN32) - target_sources(melonDS PUBLIC "${CMAKE_SOURCE_DIR}/melon.rc") - - target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32) - if (BUILD_STATIC) - target_link_libraries(melonDS imm32 winmm version setupapi -static Qt5::Core Qt5::Gui Qt5::Widgets z zstd) - else() - target_link_libraries(melonDS Qt5::Core Qt5::Gui Qt5::Widgets) - endif() -endif () + option(PORTABLE "Make a portable build that looks for its configuration in the current directory" ON) + target_sources(melonDS PUBLIC "${CMAKE_SOURCE_DIR}/melon.rc") + + target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32) + if (BUILD_STATIC) + target_link_libraries(melonDS imm32 winmm version setupapi -static Qt5::Core Qt5::Gui Qt5::Widgets z zstd) + else() + target_link_libraries(melonDS Qt5::Core Qt5::Gui Qt5::Widgets) + endif() +endif() + +if (PORTABLE) + add_definitions(-DPORTABLE) +endif() install(FILES ../../../net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) install(FILES ../../../icon/melon_16x16.png DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/16x16/apps RENAME net.kuribo64.melonDS.png) diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp index edc8d45..43f358f 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -19,7 +19,12 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <SDL2/SDL.h> +#include <QStandardPaths> +#include <QDir> +#include <QThread> +#include <QSemaphore> +#include <QOpenGLContext> + #include "Platform.h" #include "PlatformConfig.h" #include "LAN_Socket.h" @@ -27,25 +32,26 @@ #include <string> #ifdef __WIN32__ - #define NTDDI_VERSION 0x06000000 // GROSS FUCKING HACK - #include <windows.h> - //#include <knownfolders.h> // FUCK THAT SHIT - extern "C" const GUID DECLSPEC_SELECTANY FOLDERID_RoamingAppData = {0x3eb685db, 0x65f9, 0x4cf6, {0xa0, 0x3a, 0xe3, 0xef, 0x65, 0x72, 0x9f, 0x3d}}; - #include <shlobj.h> - #include <winsock2.h> - #include <ws2tcpip.h> - #define socket_t SOCKET - #define sockaddr_t SOCKADDR +#define NTDDI_VERSION 0x06000000 // GROSS FUCKING HACK +#include <windows.h> +//#include <knownfolders.h> // FUCK THAT SHIT +#include <shlobj.h> +#include <winsock2.h> +#include <ws2tcpip.h> +#include <io.h> +#define dup _dup +#define socket_t SOCKET +#define sockaddr_t SOCKADDR #else - #include <glib.h> - #include <unistd.h> - #include <arpa/inet.h> - #include <netinet/in.h> - #include <sys/select.h> - #include <sys/socket.h> - #define socket_t int - #define sockaddr_t struct sockaddr - #define closesocket close + +#include <unistd.h> +#include <netinet/in.h> +#include <sys/select.h> +#include <sys/socket.h> + +#define socket_t int +#define sockaddr_t struct sockaddr +#define closesocket close #endif #ifndef INVALID_SOCKET @@ -62,22 +68,6 @@ void* oglGetProcAddress(const char* proc); namespace Platform { - -typedef struct -{ - SDL_Thread* ID; - void (*Func)(); - -} ThreadData; - -int ThreadEntry(void* data) -{ - ThreadData* thread = (ThreadData*)data; - thread->Func(); - return 0; -} - - socket_t MPSocket; sockaddr_t MPSendAddr; u8 PacketBuffer[2048]; @@ -115,14 +105,12 @@ void Init(int argc, char** argv) strcpy(EmuDirectory, "."); } #else - const char* confdir = g_get_user_config_dir(); - const char* confname = "/melonDS"; - int cdlen = strlen(confdir); - int cnlen = strlen(confname); - EmuDirectory = new char[cdlen + cnlen + 1]; - strncpy(&EmuDirectory[0], confdir, cdlen); - strncpy(&EmuDirectory[cdlen], confname, cnlen); - EmuDirectory[cdlen+cnlen] = '\0'; + QString confdir; + QDir config(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)); + config.mkdir("melonDS"); + confdir = config.absolutePath() + "/melonDS/"; + EmuDirectory = new char[confdir.length() + 1]; + memcpy(EmuDirectory, confdir.toUtf8().data(), confdir.length()); #endif } @@ -140,280 +128,102 @@ void StopEmu() FILE* OpenFile(const char* path, const char* mode, bool mustexist) { - FILE* ret; - -#ifdef __WIN32__ - - int len = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0); - if (len < 1) return NULL; - WCHAR* fatpath = new WCHAR[len]; - int res = MultiByteToWideChar(CP_UTF8, 0, path, -1, fatpath, len); - if (res != len) { delete[] fatpath; return NULL; } // checkme? - - // this will be more than enough - WCHAR fatmode[4]; - fatmode[0] = mode[0]; - fatmode[1] = mode[1]; - fatmode[2] = mode[2]; - fatmode[3] = 0; + QFile f(path); - if (mustexist) + if (mustexist && !f.exists()) { - ret = _wfopen(fatpath, L"rb"); - if (ret) ret = _wfreopen(fatpath, fatmode, ret); + return nullptr; } - else - ret = _wfopen(fatpath, fatmode); - - delete[] fatpath; - -#else - if (mustexist) - { - ret = fopen(path, "rb"); - if (ret) ret = freopen(path, mode, ret); + QIODevice::OpenMode qmode; + if (strlen(mode) > 1 && mode[0] == 'r' && mode[1] == '+') { + qmode = QIODevice::OpenModeFlag::ReadWrite; + } else if (strlen(mode) > 1 && mode[0] == 'w' && mode[1] == '+') { + qmode = QIODevice::OpenModeFlag::Truncate | QIODevice::OpenModeFlag::ReadWrite; + } else if (mode[0] == 'w') { + qmode = QIODevice::OpenModeFlag::Truncate | QIODevice::OpenModeFlag::WriteOnly; + } else { + qmode = QIODevice::OpenModeFlag::ReadOnly; } - else - ret = fopen(path, mode); -#endif + f.open(qmode); + FILE* file = fdopen(dup(f.handle()), mode); + f.close(); - return ret; + return file; } -#if !defined(UNIX_PORTABLE) && !defined(__WIN32__) - FILE* OpenLocalFile(const char* path, const char* mode) { - std::string fullpath; - if (path[0] == '/') - { - // If it's an absolute path, just open that. - fullpath = std::string(path); - } - else - { - // Check user configuration directory - std::string confpath = std::string(g_get_user_config_dir()) + "/melonDS/"; - g_mkdir_with_parents(confpath.c_str(), 0755); - fullpath = confpath + path; - } - - return OpenFile(fullpath.c_str(), mode, mode[0] != 'w'); -} - -FILE* OpenDataFile(const char* path) -{ - const char* melondir = "melonDS"; - const char* const* sys_dirs = g_get_system_data_dirs(); - const char* user_dir = g_get_user_data_dir(); - - // First check the user's data directory - char* fullpath = g_build_path("/", user_dir, melondir, path, NULL); - if (access(fullpath, R_OK) == 0) - { - FILE* f = fopen(fullpath, "r"); - g_free(fullpath); - return f; - } - free(fullpath); - - // Then check the system data directories - for (size_t i = 0; sys_dirs[i] != NULL; i++) - { - const char* dir = sys_dirs[i]; - char* fullpath = g_build_path("/", dir, melondir, path, NULL); - - if (access(fullpath, R_OK) == 0) - { - FILE* f = fopen(fullpath, "r"); - g_free(fullpath); - return f; - } - free(fullpath); - } + QDir dir(path); + QString fullpath; - FILE* f = fopen(path, "rb"); - if (f) return f; - - return NULL; -} - -#else - -FILE* OpenLocalFile(const char* path, const char* mode) -{ - bool relpath = false; - int pathlen = strlen(path); - -#ifdef __WIN32__ - if (pathlen > 3) + if (dir.isAbsolute()) { - if (path[1] == ':' && (path[2] == '\\' || path[2] == '/')) - return OpenFile(path, mode); - } -#else - if (pathlen > 1) - { - if (path[0] == '/') - return OpenFile(path, mode); - } -#endif - - if (pathlen >= 3) - { - if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || path[2] == '\\')) - relpath = true; - } - - int emudirlen = strlen(EmuDirectory); - char* emudirpath; - if (emudirlen) - { - int len = emudirlen + 1 + pathlen + 1; - emudirpath = new char[len]; - strncpy(&emudirpath[0], EmuDirectory, emudirlen); - emudirpath[emudirlen] = '/'; - strncpy(&emudirpath[emudirlen+1], path, pathlen); - emudirpath[emudirlen+1+pathlen] = '\0'; + // If it's an absolute path, just open that. + fullpath = path; } else { - emudirpath = new char[pathlen+1]; - strncpy(&emudirpath[0], path, pathlen); - emudirpath[pathlen] = '\0'; - } - - // Locations are application directory, and AppData/melonDS on Windows or XDG_CONFIG_HOME/melonDS on Linux - - FILE* f; - - // First check current working directory - f = OpenFile(path, mode, true); - if (f) { delete[] emudirpath; return f; } - - // then emu directory - f = OpenFile(emudirpath, mode, true); - if (f) { delete[] emudirpath; return f; } - -#ifdef __WIN32__ - - // a path relative to AppData wouldn't make much sense - if (!relpath) - { - // Now check AppData - PWSTR appDataPath = NULL; - SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &appDataPath); - if (!appDataPath) - { - delete[] emudirpath; - return NULL; - } - - // this will be more than enough - WCHAR fatperm[4]; - fatperm[0] = mode[0]; - fatperm[1] = mode[1]; - fatperm[2] = mode[2]; - fatperm[3] = 0; - - int fnlen = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0); - if (fnlen < 1) { delete[] emudirpath; return NULL; } - WCHAR* wfileName = new WCHAR[fnlen]; - int res = MultiByteToWideChar(CP_UTF8, 0, path, -1, wfileName, fnlen); - if (res != fnlen) { delete[] wfileName; delete[] emudirpath; return NULL; } // checkme? - - const WCHAR* appdir = L"\\melonDS\\"; - - int pos = wcslen(appDataPath); - void* ptr = CoTaskMemRealloc(appDataPath, (pos+wcslen(appdir)+fnlen+1)*sizeof(WCHAR)); - if (!ptr) { delete[] wfileName; delete[] emudirpath; return NULL; } // oh well - appDataPath = (PWSTR)ptr; - - wcscpy(&appDataPath[pos], appdir); pos += wcslen(appdir); - wcscpy(&appDataPath[pos], wfileName); - - f = _wfopen(appDataPath, L"rb"); - if (f) f = _wfreopen(appDataPath, fatperm, f); - CoTaskMemFree(appDataPath); - delete[] wfileName; - if (f) { delete[] emudirpath; return f; } - } - +#ifdef PORTABLE + fullpath = path; #else - - if (!relpath) - { - // Now check XDG_CONFIG_HOME - // TODO: check for memory leak there - std::string fullpath = std::string(g_get_user_config_dir()) + "/melonDS/" + path; - f = OpenFile(fullpath.c_str(), mode, true); - if (f) { delete[] emudirpath; return f; } - } - + // Check user configuration directory + QDir config(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation)); + config.mkdir("melonDS"); + fullpath = config.absolutePath() + "/melonDS/"; + fullpath.append(path); #endif - - if (mode[0] != 'r') - { - f = OpenFile(emudirpath, mode); - if (f) { delete[] emudirpath; return f; } } - delete[] emudirpath; - return NULL; -} - -FILE* OpenDataFile(const char* path) -{ - return OpenLocalFile(path, "rb"); + return OpenFile(fullpath.toUtf8(), mode, mode[0] != 'w'); } -#endif - - -void* Thread_Create(void (*func)()) +void* Thread_Create(void (* func)()) { - ThreadData* data = new ThreadData; - data->Func = func; - data->ID = SDL_CreateThread(ThreadEntry, "melonDS core thread", data); - return data; + QThread* t = QThread::create(func); + t->start(); + return (void*) t; } void Thread_Free(void* thread) { - delete (ThreadData*)thread; + QThread* t = (QThread*) thread; + t->terminate(); + delete t; } void Thread_Wait(void* thread) { - SDL_WaitThread((SDL_Thread*)((ThreadData*)thread)->ID, NULL); + ((QThread*) thread)->wait(); } void* Semaphore_Create() { - return SDL_CreateSemaphore(0); + return new QSemaphore(); } void Semaphore_Free(void* sema) { - SDL_DestroySemaphore((SDL_sem*)sema); + delete (QSemaphore*) sema; } void Semaphore_Reset(void* sema) { - while (SDL_SemTryWait((SDL_sem*)sema) == 0); + QSemaphore* s = (QSemaphore*) sema; + + s->acquire(s->available()); } void Semaphore_Wait(void* sema) { - SDL_SemWait((SDL_sem*)sema); + ((QSemaphore*) sema)->acquire(); } void Semaphore_Post(void* sema) { - SDL_SemPost((SDL_sem*)sema); + ((QSemaphore*) sema)->release(); } @@ -437,44 +247,44 @@ bool MP_Init() #endif // __WIN32__ MPSocket = socket(AF_INET, SOCK_DGRAM, 0); - if (MPSocket < 0) - { - return false; - } - - res = setsockopt(MPSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt_true, sizeof(int)); - if (res < 0) - { - closesocket(MPSocket); - MPSocket = INVALID_SOCKET; - return false; - } - - sockaddr_t saddr; - saddr.sa_family = AF_INET; - *(u32*)&saddr.sa_data[2] = htonl(Config::SocketBindAnyAddr ? INADDR_ANY : INADDR_LOOPBACK); - *(u16*)&saddr.sa_data[0] = htons(7064); - res = bind(MPSocket, &saddr, sizeof(sockaddr_t)); - if (res < 0) - { - closesocket(MPSocket); - MPSocket = INVALID_SOCKET; - return false; - } - - res = setsockopt(MPSocket, SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(int)); - if (res < 0) - { - closesocket(MPSocket); - MPSocket = INVALID_SOCKET; - return false; - } - - MPSendAddr.sa_family = AF_INET; - *(u32*)&MPSendAddr.sa_data[2] = htonl(INADDR_BROADCAST); - *(u16*)&MPSendAddr.sa_data[0] = htons(7064); - - return true; + if (MPSocket < 0) + { + return false; + } + + res = setsockopt(MPSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt_true, sizeof(int)); + if (res < 0) + { + closesocket(MPSocket); + MPSocket = INVALID_SOCKET; + return false; + } + + sockaddr_t saddr; + saddr.sa_family = AF_INET; + *(u32*)&saddr.sa_data[2] = htonl(Config::SocketBindAnyAddr ? INADDR_ANY : INADDR_LOOPBACK); + *(u16*)&saddr.sa_data[0] = htons(7064); + res = bind(MPSocket, &saddr, sizeof(sockaddr_t)); + if (res < 0) + { + closesocket(MPSocket); + MPSocket = INVALID_SOCKET; + return false; + } + + res = setsockopt(MPSocket, SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(int)); + if (res < 0) + { + closesocket(MPSocket); + MPSocket = INVALID_SOCKET; + return false; + } + + MPSendAddr.sa_family = AF_INET; + *(u32*)&MPSendAddr.sa_data[2] = htonl(INADDR_BROADCAST); + *(u16*)&MPSendAddr.sa_data[0] = htons(7064); + + return true; } void MP_DeInit() @@ -515,14 +325,14 @@ int MP_RecvPacket(u8* data, bool block) return 0; fd_set fd; - struct timeval tv; + struct timeval tv; - FD_ZERO(&fd); - FD_SET(MPSocket, &fd); - tv.tv_sec = 0; - tv.tv_usec = block ? 5000 : 0; + FD_ZERO(&fd); + FD_SET(MPSocket, &fd); + tv.tv_sec = 0; + tv.tv_usec = block ? 5000 : 0; - if (!select(MPSocket+1, &fd, 0, 0, &tv)) + if (!select(MPSocket+1, &fd, 0, 0, &tv)) { return 0; } |