aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/qt_sdl/Platform.cpp
diff options
context:
space:
mode:
authorNadia Holmquist Pedersen <nadia@nhp.sh>2020-05-06 02:36:47 +0200
committerNadia Holmquist Pedersen <nadia@nhp.sh>2020-05-06 03:22:30 +0200
commit6cfe4faa56f4c7c34bf42cd600c66a2ed7966062 (patch)
tree646d0020a9c1c41cd3ef963e0a5e377c91f1abc6 /src/frontend/qt_sdl/Platform.cpp
parentffe20c1236d4f8140d25c7548ab452e7b35064bd (diff)
Use Qt abstractions for file I/O and threading on both Windows and Linux.
Diffstat (limited to 'src/frontend/qt_sdl/Platform.cpp')
-rw-r--r--src/frontend/qt_sdl/Platform.cpp537
1 files changed, 183 insertions, 354 deletions
diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp
index de8db93..ddf48e9 100644
--- a/src/frontend/qt_sdl/Platform.cpp
+++ b/src/frontend/qt_sdl/Platform.cpp
@@ -19,34 +19,36 @@
#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"
//#include "LAN_PCap.h"
-#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 <QStandardPaths>
- #include <QDir>
- #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 +64,6 @@ void Stop(bool internal);
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];
@@ -87,307 +73,151 @@ u8 PacketBuffer[2048];
void StopEmu()
{
- //Stop(true);
+ //Stop(true);
}
-
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;
+ if (!mustexist && !f.exists())
+ return nullptr;
-#else
-
- if (mustexist)
- {
- ret = fopen(path, "rb");
- if (ret) ret = freopen(path, mode, ret);
- }
- else
- ret = fopen(path, mode);
+ f.open(QIODevice::ReadOnly);
+ FILE* file = fdopen(dup(f.handle()), mode);
+ f.close();
-#endif
-
- 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
- QString confpath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/melonDS/";
- confpath.append(path);
-
- fullpath = confpath.toStdString();
- }
-
- return OpenFile(fullpath.c_str(), mode, mode[0] != 'w');
-}
-
-FILE* OpenDataFile(const char* path)
-{
- QString melondir = "melonDS";
- QStringList sys_dirs = QStandardPaths::standardLocations(QStandardPaths::DataLocation);
- QString sep = QDir::separator();
-
- const char* found = NULL;
-
- for (int i = 0; i < sys_dirs.size(); i++) {
- QString f = sys_dirs.at(i) + sep + melondir + sep + QString(path);
+ QString fullpath;
- if (QFile::exists(f)) {
- found = f.toStdString().c_str();
- break;
- }
- }
-
- if (found == NULL)
- return NULL;
-
- FILE* f = fopen(found, "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
+ fullpath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/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] == '\\')
- return OpenFile(path, mode);
- }
+#ifdef PORTABLE
+ return OpenLocalFile(path);
#else
- if (pathlen > 1)
- {
- if (path[0] == '/')
- return OpenFile(path, mode);
- }
-#endif
+ QString melondir = "/melonDS/";
+ QStringList sys_dirs = QStandardPaths::standardLocations(QStandardPaths::DataLocation);
+ QString found = nullptr;
- 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;
-
- // 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; }
+ for (int i = 0; i < sys_dirs.size(); i++)
+ {
+ QString f = sys_dirs.at(i) + melondir + path;
-#ifdef __WIN32__
+ if (QFile::exists(f))
+ {
+ found = f;
+ break;
+ }
+ }
- // 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; }
- }
+ if (found == nullptr)
+ return nullptr;
-#else
-
- if (!relpath)
- {
- // Now check XDG_CONFIG_HOME
- // TODO: check for memory leak there
- std::string fullpath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation).toStdString() + "/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)
+void* Thread_Create(void (* func)())
{
- return OpenLocalFile(path, "rb");
-}
-
-#endif
-
-
-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();
}
void* GL_GetProcAddress(const char* proc)
{
- return NULL;//uiGLGetProcAddress(proc);
+ return (void*) QOpenGLContext::globalShareContext()->getProcAddress(proc);
}
bool MP_Init()
{
- int opt_true = 1;
- int res;
+ int opt_true = 1;
+ int res;
#ifdef __WIN32__
- WSADATA wsadata;
- if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
- {
- return false;
- }
+ WSADATA wsadata;
+ if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
+ {
+ return false;
+ }
#endif // __WIN32__
- MPSocket = socket(AF_INET, SOCK_DGRAM, 0);
+ 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));
+ res = setsockopt(MPSocket, SOL_SOCKET, SO_REUSEADDR, (const char*) &opt_true, sizeof(int));
if (res < 0)
{
closesocket(MPSocket);
@@ -397,8 +227,8 @@ bool MP_Init()
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);
+ *(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)
{
@@ -407,7 +237,7 @@ bool MP_Init()
return false;
}
- res = setsockopt(MPSocket, SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(int));
+ res = setsockopt(MPSocket, SOL_SOCKET, SO_BROADCAST, (const char*) &opt_true, sizeof(int));
if (res < 0)
{
closesocket(MPSocket);
@@ -416,50 +246,50 @@ bool MP_Init()
}
MPSendAddr.sa_family = AF_INET;
- *(u32*)&MPSendAddr.sa_data[2] = htonl(INADDR_BROADCAST);
- *(u16*)&MPSendAddr.sa_data[0] = htons(7064);
+ *(u32*) &MPSendAddr.sa_data[2] = htonl(INADDR_BROADCAST);
+ *(u16*) &MPSendAddr.sa_data[0] = htons(7064);
return true;
}
void MP_DeInit()
{
- if (MPSocket >= 0)
- closesocket(MPSocket);
+ if (MPSocket >= 0)
+ closesocket(MPSocket);
#ifdef __WIN32__
- WSACleanup();
+ WSACleanup();
#endif // __WIN32__
}
int MP_SendPacket(u8* data, int len)
{
- if (MPSocket < 0)
- return 0;
-
- if (len > 2048-8)
- {
- printf("MP_SendPacket: error: packet too long (%d)\n", len);
- return 0;
- }
-
- *(u32*)&PacketBuffer[0] = htonl(0x4946494E); // NIFI
- PacketBuffer[4] = NIFI_VER;
- PacketBuffer[5] = 0;
- *(u16*)&PacketBuffer[6] = htons(len);
- memcpy(&PacketBuffer[8], data, len);
-
- int slen = sendto(MPSocket, (const char*)PacketBuffer, len+8, 0, &MPSendAddr, sizeof(sockaddr_t));
- if (slen < 8) return 0;
- return slen - 8;
+ if (MPSocket < 0)
+ return 0;
+
+ if (len > 2048 - 8)
+ {
+ printf("MP_SendPacket: error: packet too long (%d)\n", len);
+ return 0;
+ }
+
+ *(u32*) &PacketBuffer[0] = htonl(0x4946494E); // NIFI
+ PacketBuffer[4] = NIFI_VER;
+ PacketBuffer[5] = 0;
+ *(u16*) &PacketBuffer[6] = htons(len);
+ memcpy(&PacketBuffer[8], data, len);
+
+ int slen = sendto(MPSocket, (const char*) PacketBuffer, len + 8, 0, &MPSendAddr, sizeof(sockaddr_t));
+ if (slen < 8) return 0;
+ return slen - 8;
}
int MP_RecvPacket(u8* data, bool block)
{
- if (MPSocket < 0)
- return 0;
+ if (MPSocket < 0)
+ return 0;
- fd_set fd;
+ fd_set fd;
struct timeval tv;
FD_ZERO(&fd);
@@ -467,84 +297,83 @@ int MP_RecvPacket(u8* data, bool block)
tv.tv_sec = 0;
tv.tv_usec = block ? 5000 : 0;
- if (!select(MPSocket+1, &fd, 0, 0, &tv))
- {
- return 0;
- }
-
- sockaddr_t fromAddr;
- socklen_t fromLen = sizeof(sockaddr_t);
- int rlen = recvfrom(MPSocket, (char*)PacketBuffer, 2048, 0, &fromAddr, &fromLen);
- if (rlen < 8+24)
- {
- return 0;
- }
- rlen -= 8;
-
- if (ntohl(*(u32*)&PacketBuffer[0]) != 0x4946494E)
- {
- return 0;
- }
-
- if (PacketBuffer[4] != NIFI_VER)
- {
- return 0;
- }
-
- if (ntohs(*(u16*)&PacketBuffer[6]) != rlen)
- {
- return 0;
- }
-
- memcpy(data, &PacketBuffer[8], rlen);
- return rlen;
-}
+ if (!select(MPSocket + 1, &fd, 0, 0, &tv))
+ {
+ return 0;
+ }
+ sockaddr_t fromAddr;
+ socklen_t fromLen = sizeof(sockaddr_t);
+ int rlen = recvfrom(MPSocket, (char*) PacketBuffer, 2048, 0, &fromAddr, &fromLen);
+ if (rlen < 8 + 24)
+ {
+ return 0;
+ }
+ rlen -= 8;
+
+ if (ntohl(*(u32*) &PacketBuffer[0]) != 0x4946494E)
+ {
+ return 0;
+ }
+
+ if (PacketBuffer[4] != NIFI_VER)
+ {
+ return 0;
+ }
+
+ if (ntohs(*(u16*) &PacketBuffer[6]) != rlen)
+ {
+ return 0;
+ }
+
+ memcpy(data, &PacketBuffer[8], rlen);
+ return rlen;
+}
bool LAN_Init()
{
- /*if (Config::DirectLAN)
- {
- if (!LAN_PCap::Init(true))
- return false;
- }
- else
- {
- if (!LAN_Socket::Init())
- return false;
- }*/
-
- return true;
+ /*if (Config::DirectLAN)
+ {
+ if (!LAN_PCap::Init(true))
+ return false;
+ }
+ else
+ {
+ if (!LAN_Socket::Init())
+ return false;
+ }*/
+
+ return true;
}
void LAN_DeInit()
{
- // checkme. blarg
- //if (Config::DirectLAN)
- // LAN_PCap::DeInit();
- //else
- // LAN_Socket::DeInit();
- /*LAN_PCap::DeInit();
- LAN_Socket::DeInit();*/
+ // checkme. blarg
+ //if (Config::DirectLAN)
+ // LAN_PCap::DeInit();
+ //else
+ // LAN_Socket::DeInit();
+ /*LAN_PCap::DeInit();
+ LAN_Socket::DeInit();*/
}
int LAN_SendPacket(u8* data, int len)
{
- /*if (Config::DirectLAN)
- return LAN_PCap::SendPacket(data, len);
- else
- return LAN_Socket::SendPacket(data, len);*/
- return 0;
+ /*if (Config::DirectLAN)
+ return LAN_PCap::SendPacket(data, len);
+ else
+ return LAN_Socket::SendPacket(data, len);*/
+ return 0;
}
int LAN_RecvPacket(u8* data)
{
- /*if (Config::DirectLAN)
- return LAN_PCap::RecvPacket(data);
- else
- return LAN_Socket::RecvPacket(data);*/
- return 0;
+ /*if (Config::DirectLAN)
+ return LAN_PCap::RecvPacket(data);
+ else
+ return LAN_Socket::RecvPacket(data);*/
+ return 0;
}