diff options
-rw-r--r-- | src/frontend/qt_sdl/CMakeLists.txt | 41 | ||||
-rw-r--r-- | src/frontend/qt_sdl/Platform.cpp | 359 |
2 files changed, 105 insertions, 295 deletions
diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt index 62d6e60..1559cd4 100644 --- a/src/frontend/qt_sdl/CMakeLists.txt +++ b/src/frontend/qt_sdl/CMakeLists.txt @@ -16,13 +16,13 @@ SET(SOURCES_QT_SDL font.h Platform.cpp PlatformConfig.cpp - + ../Util_ROM.cpp ../Util_Video.cpp ../Util_Audio.cpp ../FrontendUtil.h ../mic_blow.h - + ../../../melon.qrc ) @@ -66,42 +66,23 @@ else() 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) + 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 () +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..47befb0 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,24 @@ #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> +#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 +66,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 +103,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 +126,123 @@ void StopEmu() FILE* OpenFile(const char* path, const char* mode, bool mustexist) { - FILE* ret; - -#ifdef __WIN32__ + QFile f(path); - 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; - - if (mustexist) - { - ret = _wfopen(fatpath, L"rb"); - if (ret) ret = _wfreopen(fatpath, fatmode, ret); - } - else - ret = _wfopen(fatpath, fatmode); - - delete[] fatpath; - -#else + if (mustexist && !f.exists()) + { + return nullptr; + } - if (mustexist) - { - ret = fopen(path, "rb"); - if (ret) ret = freopen(path, mode, ret); - } - else - ret = fopen(path, mode); + QIODevice::OpenMode qmode = mode[0] == 'w' ? QIODevice::ReadWrite : QIODevice::ReadOnly; -#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(); + QString fullpath; - // 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); - } - - FILE* f = fopen(path, "rb"); - if (f) return f; + if (path[0] == '/') + { + // If it's an absolute path, just open that. + fullpath = path; + } + else + { +#ifdef PORTABLE + fullpath = QString("./") + path; +#else + // Check user configuration directory + QDir config(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)); + config.mkdir("melonDS"); + fullpath = config.absolutePath() + "/melonDS/"; + fullpath.append(path); +#endif + } - return NULL; + return OpenFile(fullpath.toUtf8(), mode, mode[0] != 'w'); } -#else - -FILE* OpenLocalFile(const char* path, const char* mode) +FILE* OpenDataFile(const char* path) { - bool relpath = false; - int pathlen = strlen(path); - -#ifdef __WIN32__ - if (pathlen > 3) - { - if (path[1] == ':' && (path[2] == '\\' || path[2] == '/')) - return OpenFile(path, mode); - } +#ifdef PORTABLE + return OpenLocalFile(path); #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'; - } - 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; + QString melondir = "/melonDS/"; + QStringList sys_dirs = QStandardPaths::standardLocations(QStandardPaths::DataLocation); + QString found = nullptr; - // 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; - } + for (int i = 0; i < sys_dirs.size(); i++) + { + QString f = sys_dirs.at(i) + melondir + path; - // 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; } - } + if (QFile::exists(f)) + { + found = f; + break; + } + } -#else + if (found == nullptr) + return nullptr; - 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; } - } + FILE* f = OpenFile(found.toUtf8(), "rb", false); + if (f) + return f; + return nullptr; #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"); } -#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(); } |