Merge branch 'master' into global-config-screenshot

This commit is contained in:
Cacodemon345
2022-12-03 20:29:26 +06:00
committed by GitHub
687 changed files with 90165 additions and 81964 deletions

View File

@@ -44,23 +44,28 @@
#include "qt_progsettings.hpp"
#ifdef Q_OS_UNIX
#include <sys/mman.h>
# include <sys/mman.h>
#endif
// static QByteArray buf;
extern QElapsedTimer elapsed_timer;
extern MainWindow* main_window;
QElapsedTimer elapsed_timer;
extern MainWindow *main_window;
QElapsedTimer elapsed_timer;
static std::atomic_int blitmx_contention = 0;
static std::atomic_int blitmx_contention = 0;
static std::recursive_mutex blitmx;
class CharPointer {
public:
CharPointer(char* buf, int size) : b(buf), s(size) {}
CharPointer& operator=(const QByteArray &ba) {
CharPointer(char *buf, int size)
: b(buf)
, s(size)
{
}
CharPointer &operator=(const QByteArray &ba)
{
if (s > 0) {
strncpy(b, ba.data(), s-1);
strncpy(b, ba.data(), s - 1);
b[s] = 0;
} else {
// if we haven't been told the length of b, just assume enough
@@ -70,9 +75,10 @@ public:
}
return *this;
}
private:
char* b;
int s;
char *b;
int s;
};
extern "C" {
@@ -101,18 +107,19 @@ extern "C" {
#include "../cpu/cpu.h"
#include <86box/plat.h>
volatile int cpu_thread_run = 1;
int mouse_capture = 0;
int fixed_size_x = 640;
int fixed_size_y = 480;
int rctrl_is_lalt = 0;
int update_icons = 1;
int kbd_req_capture = 0;
int hide_status_bar = 0;
int hide_tool_bar = 0;
uint32_t lang_id = 0x0409, lang_sys = 0x0409; // Multilangual UI variables, for now all set to LCID of en-US
volatile int cpu_thread_run = 1;
int mouse_capture = 0;
int fixed_size_x = 640;
int fixed_size_y = 480;
int rctrl_is_lalt = 0;
int update_icons = 1;
int kbd_req_capture = 0;
int hide_status_bar = 0;
int hide_tool_bar = 0;
uint32_t lang_id = 0x0409, lang_sys = 0x0409; // Multilangual UI variables, for now all set to LCID of en-US
int stricmp(const char* s1, const char* s2)
int
stricmp(const char *s1, const char *s2)
{
#ifdef Q_OS_WINDOWS
return _stricmp(s1, s2);
@@ -121,7 +128,8 @@ int stricmp(const char* s1, const char* s2)
#endif
}
int strnicmp(const char *s1, const char *s2, size_t n)
int
strnicmp(const char *s1, const char *s2, size_t n)
{
#ifdef Q_OS_WINDOWS
return _strnicmp(s1, s2, n);
@@ -134,14 +142,15 @@ void
do_stop(void)
{
cpu_thread_run = 0;
//main_window->close();
// main_window->close();
}
void plat_get_exe_name(char *s, int size)
void
plat_get_exe_name(char *s, int size)
{
QByteArray exepath_temp = QCoreApplication::applicationDirPath().toLocal8Bit();
memcpy(s, exepath_temp.data(), std::min((qsizetype)exepath_temp.size(),(qsizetype)size));
memcpy(s, exepath_temp.data(), std::min((qsizetype) exepath_temp.size(), (qsizetype) size));
path_slash(s);
}
@@ -163,7 +172,7 @@ plat_fopen(const char *path, const char *mode)
{
#if defined(Q_OS_MACOS) or defined(Q_OS_LINUX)
QFileInfo fi(path);
QString filename = (fi.isRelative() && !fi.filePath().isEmpty()) ? usr_path + fi.filePath() : fi.filePath();
QString filename = (fi.isRelative() && !fi.filePath().isEmpty()) ? usr_path + fi.filePath() : fi.filePath();
return fopen(filename.toUtf8().constData(), mode);
#else
return fopen(QString::fromUtf8(path).toLocal8Bit(), mode);
@@ -175,7 +184,7 @@ plat_fopen64(const char *path, const char *mode)
{
#if defined(Q_OS_MACOS) or defined(Q_OS_LINUX)
QFileInfo fi(path);
QString filename = (fi.isRelative() && !fi.filePath().isEmpty()) ? usr_path + fi.filePath() : fi.filePath();
QString filename = (fi.isRelative() && !fi.filePath().isEmpty()) ? usr_path + fi.filePath() : fi.filePath();
return fopen(filename.toUtf8().constData(), mode);
#else
return fopen(QString::fromUtf8(path).toLocal8Bit(), mode);
@@ -220,9 +229,9 @@ path_get_extension(char *s)
auto len = strlen(s);
auto idx = QByteArray::fromRawData(s, len).lastIndexOf('.');
if (idx >= 0) {
return s+idx+1;
return s + idx + 1;
}
return s+len;
return s + len;
}
char *
@@ -232,16 +241,16 @@ path_get_filename(char *s)
int c = strlen(s) - 1;
while (c > 0) {
if (s[c] == '/' || s[c] == '\\')
return(&s[c+1]);
c--;
if (s[c] == '/' || s[c] == '\\')
return (&s[c + 1]);
c--;
}
return(s);
return (s);
#else
auto idx = QByteArray::fromRawData(s, strlen(s)).lastIndexOf(QDir::separator().toLatin1());
auto idx = QByteArray::fromRawData(s, strlen(s)).lastIndexOf(QDir::separator().toLatin1());
if (idx >= 0) {
return s+idx+1;
return s + idx + 1;
}
return s;
#endif
@@ -261,12 +270,12 @@ path_abs(char *path)
}
void
path_normalize(char* path)
path_normalize(char *path)
{
#ifdef Q_OS_WINDOWS
while (*path++ != 0)
{
if (*path == '\\') *path = '/';
while (*path++ != 0) {
if (*path == '\\')
*path = '/';
}
#endif
}
@@ -274,11 +283,11 @@ path_normalize(char* path)
void
path_slash(char *path)
{
auto len = strlen(path);
auto len = strlen(path);
auto separator = '/';
if (path[len-1] != separator) {
path[len] = separator;
path[len+1] = 0;
if (path[len - 1] != separator) {
path[len] = separator;
path[len + 1] = 0;
}
path_normalize(path);
}
@@ -300,12 +309,14 @@ plat_tempfile(char *bufp, char *prefix, char *suffix)
name.append(QString("%1-").arg(prefix));
}
name.append(QDateTime::currentDateTime().toString("yyyyMMdd-hhmmss-zzzz"));
if (suffix) name.append(suffix);
strcpy(bufp, name.toUtf8().data());
name.append(QDateTime::currentDateTime().toString("yyyyMMdd-hhmmss-zzzz"));
if (suffix)
name.append(suffix);
strcpy(bufp, name.toUtf8().data());
}
void plat_remove(char* path)
void
plat_remove(char *path)
{
QFile(path).remove();
}
@@ -316,11 +327,11 @@ plat_mmap(size_t size, uint8_t executable)
#if defined Q_OS_WINDOWS
return VirtualAlloc(NULL, size, MEM_COMMIT, executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE);
#elif defined Q_OS_UNIX
#if defined Q_OS_DARWIN && defined MAP_JIT
# if defined Q_OS_DARWIN && defined MAP_JIT
void *ret = mmap(0, size, PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0), MAP_ANON | MAP_PRIVATE | (executable ? MAP_JIT : 0), -1, 0);
#else
# else
void *ret = mmap(0, size, PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0), MAP_ANON | MAP_PRIVATE, -1, 0);
#endif
# endif
return (ret == MAP_FAILED) ? nullptr : ret;
#endif
}
@@ -339,12 +350,12 @@ void
plat_pause(int p)
{
static wchar_t oldtitle[512];
wchar_t title[1024], paused_msg[512];
wchar_t title[1024], paused_msg[512];
if (p == dopause) {
#ifdef Q_OS_WINDOWS
if (source_hwnd)
PostMessage((HWND)(uintptr_t)source_hwnd, WM_SENDSTATUS, (WPARAM)!!p, (LPARAM)(HWND)main_window->winId());
PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDSTATUS, (WPARAM) !!p, (LPARAM) (HWND) main_window->winId());
#endif
return;
}
@@ -354,8 +365,8 @@ plat_pause(int p)
dopause = p;
if (p) {
if (mouse_capture)
plat_mouse_capture(0);
if (mouse_capture)
plat_mouse_capture(0);
wcsncpy(oldtitle, ui_window_title(NULL), sizeof_w(oldtitle) - 1);
wcscpy(title, oldtitle);
@@ -370,12 +381,12 @@ plat_pause(int p)
#ifdef Q_OS_WINDOWS
if (source_hwnd)
PostMessage((HWND)(uintptr_t)source_hwnd, WM_SENDSTATUS, (WPARAM)!!p, (LPARAM)(HWND)main_window->winId());
PostMessage((HWND) (uintptr_t) source_hwnd, WM_SENDSTATUS, (WPARAM) !!p, (LPARAM) (HWND) main_window->winId());
#endif
}
// because we can't include nvr.h because it's got fields named new
extern int nvr_save(void);
extern int nvr_save(void);
void
plat_power_off(void)
@@ -393,44 +404,45 @@ plat_power_off(void)
QTimer::singleShot(0, (const QWidget *) main_window, &QMainWindow::close);
}
void set_language(uint32_t id) {
void
set_language(uint32_t id)
{
lang_id = id;
}
extern "C++"
{
QMap<uint32_t, QPair<QString, QString>> ProgSettings::lcid_langcode =
{
{0x0405, {"cs-CZ", "Czech (Czech Republic)"} },
{0x0407, {"de-DE", "German (Germany)"} },
{0x0409, {"en-US", "English (United States)"} },
{0x0809, {"en-GB", "English (United Kingdom)"} },
{0x0C0A, {"es-ES", "Spanish (Spain)"} },
{0x040B, {"fi-FI", "Finnish (Finland)"} },
{0x040C, {"fr-FR", "French (France)"} },
{0x041A, {"hr-HR", "Croatian (Croatia)"} },
{0x040E, {"hu-HU", "Hungarian (Hungary)"} },
{0x0410, {"it-IT", "Italian (Italy)"} },
{0x0411, {"ja-JP", "Japanese (Japan)"} },
{0x0412, {"ko-KR", "Korean (Korea)"} },
{0x0415, {"pl-PL", "Polish (Poland)"} },
{0x0416, {"pt-BR", "Portuguese (Brazil)"} },
{0x0816, {"pt-PT", "Portuguese (Portugal)"} },
{0x0419, {"ru-RU", "Russian (Russia)"} },
{0x0424, {"sl-SI", "Slovenian (Slovenia)"} },
{0x041F, {"tr-TR", "Turkish (Turkey)"} },
{0x0422, {"uk-UA", "Ukrainian (Ukraine)"} },
{0x0804, {"zh-CN", "Chinese (China)"} },
{0xFFFF, {"system", "(System Default)"} },
};
extern "C++" {
QMap<uint32_t, QPair<QString, QString>> ProgSettings::lcid_langcode = {
{0x0405, { "cs-CZ", "Czech (Czech Republic)" } },
{ 0x0407, { "de-DE", "German (Germany)" } },
{ 0x0409, { "en-US", "English (United States)" } },
{ 0x0809, { "en-GB", "English (United Kingdom)" }},
{ 0x0C0A, { "es-ES", "Spanish (Spain)" } },
{ 0x040B, { "fi-FI", "Finnish (Finland)" } },
{ 0x040C, { "fr-FR", "French (France)" } },
{ 0x041A, { "hr-HR", "Croatian (Croatia)" } },
{ 0x040E, { "hu-HU", "Hungarian (Hungary)" } },
{ 0x0410, { "it-IT", "Italian (Italy)" } },
{ 0x0411, { "ja-JP", "Japanese (Japan)" } },
{ 0x0412, { "ko-KR", "Korean (Korea)" } },
{ 0x0415, { "pl-PL", "Polish (Poland)" } },
{ 0x0416, { "pt-BR", "Portuguese (Brazil)" } },
{ 0x0816, { "pt-PT", "Portuguese (Portugal)" } },
{ 0x0419, { "ru-RU", "Russian (Russia)" } },
{ 0x0424, { "sl-SI", "Slovenian (Slovenia)" } },
{ 0x041F, { "tr-TR", "Turkish (Turkey)" } },
{ 0x0422, { "uk-UA", "Ukrainian (Ukraine)" } },
{ 0x0804, { "zh-CN", "Chinese (China)" } },
{ 0x0404, { "zh-TW", "Chinese (Taiwan)" } },
{ 0xFFFF, { "system", "(System Default)" } },
};
}
/* Sets up the program language before initialization. */
uint32_t plat_language_code(char* langcode) {
for (auto& curKey : ProgSettings::lcid_langcode.keys())
{
if (ProgSettings::lcid_langcode[curKey].first == langcode)
{
uint32_t
plat_language_code(char *langcode)
{
for (auto &curKey : ProgSettings::lcid_langcode.keys()) {
if (ProgSettings::lcid_langcode[curKey].first == langcode) {
return curKey;
}
}
@@ -438,9 +450,10 @@ uint32_t plat_language_code(char* langcode) {
}
/* Converts back the language code to LCID */
void plat_language_code_r(uint32_t lcid, char* outbuf, int len) {
if (!ProgSettings::lcid_langcode.contains(lcid))
{
void
plat_language_code_r(uint32_t lcid, char *outbuf, int len)
{
if (!ProgSettings::lcid_langcode.contains(lcid)) {
qstrncpy(outbuf, "system", len);
return;
}
@@ -449,25 +462,25 @@ void plat_language_code_r(uint32_t lcid, char* outbuf, int len) {
}
#ifndef Q_OS_WINDOWS
void* dynld_module(const char *name, dllimp_t *table)
void *
dynld_module(const char *name, dllimp_t *table)
{
QString libraryName = name;
QFileInfo fi(libraryName);
QStringList removeSuffixes = {"dll", "dylib", "so"};
QString libraryName = name;
QFileInfo fi(libraryName);
QStringList removeSuffixes = { "dll", "dylib", "so" };
if (removeSuffixes.contains(fi.suffix())) {
libraryName = fi.completeBaseName();
}
auto lib = std::unique_ptr<QLibrary>(new QLibrary(libraryName));
if (lib->load()) {
for (auto imp = table; imp->name != nullptr; imp++)
{
for (auto imp = table; imp->name != nullptr; imp++) {
auto ptr = lib->resolve(imp->name);
if (ptr == nullptr) {
return nullptr;
}
auto imp_ptr = reinterpret_cast<void**>(imp->func);
*imp_ptr = reinterpret_cast<void*>(ptr);
auto imp_ptr = reinterpret_cast<void **>(imp->func);
*imp_ptr = reinterpret_cast<void *>(ptr);
}
} else {
return nullptr;
@@ -476,13 +489,15 @@ void* dynld_module(const char *name, dllimp_t *table)
return lib.release();
}
void dynld_close(void *handle)
void
dynld_close(void *handle)
{
delete reinterpret_cast<QLibrary*>(handle);
delete reinterpret_cast<QLibrary *>(handle);
}
#endif
void startblit()
void
startblit()
{
blitmx_contention++;
if (blitmx.try_lock()) {
@@ -492,7 +507,8 @@ void startblit()
blitmx.lock();
}
void endblit()
void
endblit()
{
blitmx_contention--;
blitmx.unlock();
@@ -503,33 +519,38 @@ void endblit()
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
}
#ifdef Q_OS_WINDOWS
size_t mbstoc16s(uint16_t dst[], const char src[], int len)
size_t
mbstoc16s(uint16_t dst[], const char src[], int len)
{
if (src == NULL) return 0;
if (len < 0) return 0;
if (src == NULL)
return 0;
if (len < 0)
return 0;
size_t ret = MultiByteToWideChar(CP_UTF8, 0, src, -1, reinterpret_cast<LPWSTR>(dst), dst == NULL ? 0 : len);
if (!ret) {
return -1;
return -1;
}
return ret;
}
size_t c16stombs(char dst[], const uint16_t src[], int len)
size_t
c16stombs(char dst[], const uint16_t src[], int len)
{
if (src == NULL) return 0;
if (len < 0) return 0;
if (src == NULL)
return 0;
if (len < 0)
return 0;
size_t ret = WideCharToMultiByte(CP_UTF8, 0, reinterpret_cast<LPCWCH>(src), -1, dst, dst == NULL ? 0 : len, NULL, NULL);
if (!ret) {
return -1;
return -1;
}
return ret;
@@ -537,69 +558,68 @@ size_t c16stombs(char dst[], const uint16_t src[], int len)
#endif
#ifdef _WIN32
#define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll"
#define LIB_NAME_GS "gsdll32.dll"
#define LIB_NAME_FREETYPE "freetype.dll"
#define MOUSE_CAPTURE_KEYSEQ "F8+F12"
# define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll"
# define LIB_NAME_GS "gsdll32.dll"
# define LIB_NAME_FREETYPE "freetype.dll"
# define MOUSE_CAPTURE_KEYSEQ "F8+F12"
#else
#define LIB_NAME_FLUIDSYNTH "libfluidsynth"
#define LIB_NAME_GS "libgs"
#define LIB_NAME_FREETYPE "libfreetype"
#define MOUSE_CAPTURE_KEYSEQ "CTRL-END"
# define LIB_NAME_FLUIDSYNTH "libfluidsynth"
# define LIB_NAME_GS "libgs"
# define LIB_NAME_FREETYPE "libfreetype"
# define MOUSE_CAPTURE_KEYSEQ "CTRL-END"
#endif
QMap<int, std::wstring> ProgSettings::translatedstrings;
void ProgSettings::reloadStrings()
void
ProgSettings::reloadStrings()
{
translatedstrings.clear();
translatedstrings[IDS_2077] = QCoreApplication::translate("", "Click to capture mouse").toStdWString();
translatedstrings[IDS_2078] = QCoreApplication::translate("", "Press F8+F12 to release mouse").replace("F8+F12", MOUSE_CAPTURE_KEYSEQ).replace("CTRL-END", QLocale::system().name() == "de_DE" ? "Strg+Ende" : "CTRL-END").toStdWString();
translatedstrings[IDS_2079] = QCoreApplication::translate("", "Press F8+F12 or middle button to release mouse").replace("F8+F12", MOUSE_CAPTURE_KEYSEQ).replace("CTRL-END", QLocale::system().name() == "de_DE" ? "Strg+Ende" : "CTRL-END").toStdWString();
translatedstrings[IDS_2080] = QCoreApplication::translate("", "Failed to initialize FluidSynth").toStdWString();
translatedstrings[IDS_2130] = QCoreApplication::translate("", "Invalid configuration").toStdWString();
translatedstrings[IDS_2131] = QCoreApplication::translate("", "Invalid configuration").toStdWString();
translatedstrings[IDS_4099] = QCoreApplication::translate("", "MFM/RLL or ESDI CD-ROM drives never existed").toStdWString();
translatedstrings[IDS_2093] = QCoreApplication::translate("", "Failed to set up PCap").toStdWString();
translatedstrings[IDS_2094] = QCoreApplication::translate("", "No PCap devices found").toStdWString();
translatedstrings[IDS_2095] = QCoreApplication::translate("", "Invalid PCap device").toStdWString();
translatedstrings[IDS_2110] = QCoreApplication::translate("", "Unable to initialize FreeType").toStdWString();
translatedstrings[IDS_2111] = QCoreApplication::translate("", "Unable to initialize SDL, libsdl2 is required").toStdWString();
translatedstrings[IDS_2129] = QCoreApplication::translate("", "Make sure libpcap is installed and that you are on a libpcap-compatible network connection.").toStdWString();
translatedstrings[IDS_2114] = QCoreApplication::translate("", "Unable to initialize Ghostscript").toStdWString();
translatedstrings[IDS_2094] = QCoreApplication::translate("", "Failed to set up PCap").toStdWString();
translatedstrings[IDS_2095] = QCoreApplication::translate("", "No PCap devices found").toStdWString();
translatedstrings[IDS_2096] = QCoreApplication::translate("", "Invalid PCap device").toStdWString();
translatedstrings[IDS_2111] = QCoreApplication::translate("", "Unable to initialize FreeType").toStdWString();
translatedstrings[IDS_2112] = QCoreApplication::translate("", "Unable to initialize SDL, libsdl2 is required").toStdWString();
translatedstrings[IDS_2130] = QCoreApplication::translate("", "Make sure libpcap is installed and that you are on a libpcap-compatible network connection.").toStdWString();
translatedstrings[IDS_2115] = QCoreApplication::translate("", "Unable to initialize Ghostscript").toStdWString();
translatedstrings[IDS_2063] = QCoreApplication::translate("", "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine.").toStdWString();
translatedstrings[IDS_2064] = QCoreApplication::translate("", "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card.").toStdWString();
translatedstrings[IDS_2128] = QCoreApplication::translate("", "Hardware not available").toStdWString();
translatedstrings[IDS_2142] = QCoreApplication::translate("", "Monitor in sleep mode").toStdWString();
translatedstrings[IDS_2120] = QCoreApplication::translate("", "No ROMs found").toStdWString();
translatedstrings[IDS_2129] = QCoreApplication::translate("", "Hardware not available").toStdWString();
translatedstrings[IDS_2143] = QCoreApplication::translate("", "Monitor in sleep mode").toStdWString();
translatedstrings[IDS_2121] = QCoreApplication::translate("", "No ROMs found").toStdWString();
translatedstrings[IDS_2056] = QCoreApplication::translate("", "86Box could not find any usable ROM images.\n\nPlease <a href=\"https://github.com/86Box/roms/releases/latest\">download</a> a ROM set and extract it into the \"roms\" directory.").toStdWString();
auto flsynthstr = QCoreApplication::translate("", " is required for FluidSynth MIDI output.");
if (flsynthstr.contains("libfluidsynth"))
{
if (flsynthstr.contains("libfluidsynth")) {
flsynthstr.replace("libfluidsynth", LIB_NAME_FLUIDSYNTH);
}
else flsynthstr.prepend(LIB_NAME_FLUIDSYNTH);
translatedstrings[IDS_2133] = flsynthstr.toStdWString();
auto gssynthstr = QCoreApplication::translate("", " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files.");
if (gssynthstr.contains("libgs"))
{
} else
flsynthstr.prepend(LIB_NAME_FLUIDSYNTH);
translatedstrings[IDS_2134] = flsynthstr.toStdWString();
auto gssynthstr = QCoreApplication::translate("", " is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files.");
if (gssynthstr.contains("libgs")) {
gssynthstr.replace("libgs", LIB_NAME_GS);
}
else gssynthstr.prepend(LIB_NAME_GS);
translatedstrings[IDS_2132] = gssynthstr.toStdWString();
auto ftsynthstr = QCoreApplication::translate("", " is required for ESC/P printer emulation.");
if (ftsynthstr.contains("libfreetype"))
{
} else
gssynthstr.prepend(LIB_NAME_GS);
translatedstrings[IDS_2133] = gssynthstr.toStdWString();
auto ftsynthstr = QCoreApplication::translate("", " is required for ESC/P printer emulation.");
if (ftsynthstr.contains("libfreetype")) {
ftsynthstr.replace("libfreetype", LIB_NAME_FREETYPE);
}
else ftsynthstr.prepend(LIB_NAME_FREETYPE);
translatedstrings[IDS_2131] = ftsynthstr.toStdWString();
} else
ftsynthstr.prepend(LIB_NAME_FREETYPE);
translatedstrings[IDS_2132] = ftsynthstr.toStdWString();
}
wchar_t* plat_get_string(int i)
wchar_t *
plat_get_string(int i)
{
if (ProgSettings::translatedstrings.empty()) ProgSettings::reloadStrings();
if (ProgSettings::translatedstrings.empty())
ProgSettings::reloadStrings();
return ProgSettings::translatedstrings[i].data();
}
@@ -635,7 +655,7 @@ plat_init_rom_paths()
paths.removeLast();
#endif
for (auto& path : paths) {
for (auto &path : paths) {
#ifdef __APPLE__
rom_add_path(QDir(path).filePath("net.86Box.86Box/roms").toUtf8().constData());
#else