qt: Add support for Haiku

* OpenAL backend is enabled by default on Haiku
* bswap include now makes use of builtins if they exist
* Use a local fgetws method for Haiku to avoid crashes
* OpenGL renderers are completely disabled on Haiku (they do not work)
* Software renderer is a widget, not a window on Haiku (fixes blank screen)
* Add option to disable System MIDI at compile time
This commit is contained in:
Cacodemon345
2022-03-11 12:03:54 +06:00
parent 1791ccdeb6
commit c1f9d35de8
17 changed files with 337 additions and 33 deletions

View File

@@ -114,7 +114,13 @@ set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
# ------ ----------- ----
option(RELEASE "Release build" OFF)
option(DYNAREC "Dynamic recompiler" ON)
if (HAIKU)
option(OPENAL "OpenAL" ON)
option(SYSTEM_MIDI "System MIDI" OFF)
else()
option(OPENAL "OpenAL" OFF)
option(SYSTEM_MIDI "System MIDI" ON)
endif()
option(FLUIDSYNTH "FluidSynth" ON)
option(MUNT "MUNT" ON)
option(DINPUT "DirectInput" OFF)

View File

@@ -100,18 +100,20 @@ find_package(PNG REQUIRED)
include_directories(${PNG_INCLUDE_DIRS})
target_link_libraries(86Box PNG::PNG)
if(VCPKG_TOOLCHAIN)
# vcpkg includes a config file for rtmidi
find_package(RtMidi REQUIRED)
target_link_libraries(86Box RtMidi::rtmidi)
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(RTMIDI REQUIRED IMPORTED_TARGET rtmidi)
target_link_libraries(86Box PkgConfig::RTMIDI)
if(SYSTEM_MIDI)
if(VCPKG_TOOLCHAIN)
# vcpkg includes a config file for rtmidi
find_package(RtMidi REQUIRED)
target_link_libraries(86Box RtMidi::rtmidi)
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(RTMIDI REQUIRED IMPORTED_TARGET rtmidi)
target_link_libraries(86Box PkgConfig::RTMIDI)
if(WIN32)
target_link_libraries(PkgConfig::RTMIDI INTERFACE winmm)
endif()
if(WIN32)
target_link_libraries(PkgConfig::RTMIDI INTERFACE winmm)
endif()
endif()
endif()
configure_file(include/86box/version.h.in include/86box/version.h @ONLY)
@@ -188,6 +190,7 @@ elseif(WIN32)
OPTIONAL)
endif()
add_subdirectory(device)
add_subdirectory(disk)
add_subdirectory(floppy)

View File

@@ -21,7 +21,7 @@
#include "codegen_ops.h"
#include "codegen_ops_x86-64.h"
#if defined(__unix__) || defined(__APPLE__)
#if defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
#include <sys/mman.h>
#include <unistd.h>
#endif
@@ -66,7 +66,7 @@ void codegen_init()
#if _WIN64
codeblock = VirtualAlloc(NULL, BLOCK_SIZE * sizeof(codeblock_t), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#elif defined(__unix__) || defined(__APPLE__)
#elif defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
codeblock = mmap(NULL, BLOCK_SIZE * sizeof(codeblock_t), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
#else
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));

View File

@@ -1,4 +1,4 @@
#if defined(__linux__) || defined(__APPLE__)
#if defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>

View File

@@ -300,6 +300,27 @@ config_detect_bom(char *fn)
return 0;
}
#ifdef __HAIKU__
/* Local version of fgetws to avoid a crash */
static wchar_t*
config_fgetws(wchar_t *str, int count, FILE* stream)
{
int i = 0;
if (feof(stream)) return NULL;
for (i = 0; i < count; i++) {
wint_t curChar = fgetwc(stream);
if (curChar == WEOF) {
if (i + 1 < count) str[i + 1] = 0;
return feof(stream) ? str : NULL;
}
str[i] = curChar;
if (curChar == '\n') break;
}
if (i + 1 < count) str[i + 1] = 0;
return str;
}
#endif
/* Read and parse the configuration file into memory. */
static int
config_read(char *fn)
@@ -328,7 +349,11 @@ config_read(char *fn)
while (1) {
memset(buff, 0x00, sizeof(buff));
#ifdef __HAIKU__
config_fgetws(buff, sizeof_w(buff), f);
#else
fgetws(buff, sizeof_w(buff), f);
#endif
if (feof(f)) break;
/* Make sure there are no stray newlines or hard-returns in there. */

View File

@@ -73,20 +73,32 @@
)
#endif /*HAVE_BYTESWAP_H*/
#if defined __has_builtin && __has_builtin(__builtin_bswap16)
#define bswap16(x) __builtin_bswap16(x)
#else
static __inline uint16_t bswap16(uint16_t x)
{
return bswap_16(x);
}
#endif
#if defined __has_builtin && __has_builtin(__builtin_bswap32)
#define bswap32(x) __builtin_bswap32(x)
#else
static __inline uint32_t bswap32(uint32_t x)
{
return bswap_32(x);
}
#endif
#if defined __has_builtin && __has_builtin(__builtin_bswap64)
#define bswap64(x) __builtin_bswap64(x)
#else
static __inline uint64_t bswap64(uint64_t x)
{
return bswap_64(x);
}
#endif
static __inline void bswap16s(uint16_t *s)
{

View File

@@ -40,7 +40,7 @@ extern int stricmp(const char* s1, const char* s2);
extern int strnicmp(const char* s1, const char* s2, size_t n);
#endif
#if (defined(__unix__) || defined(__APPLE__)) && !defined(__linux__)
#if (defined(__HAIKU__) || defined(__unix__) || defined(__APPLE__)) && !defined(__linux__)
/* FreeBSD has largefile by default. */
# define fopen64 fopen
# define fseeko64 fseeko

View File

@@ -27,3 +27,7 @@ else()
add_subdirectory(slirp)
target_link_libraries(86Box slirp)
endif()
if (HAIKU)
target_link_libraries(86Box network)
endif()

View File

@@ -259,7 +259,7 @@ if (APPLE AND CMAKE_MACOSX_BUNDLE)
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX_ABSOLUTE}/86Box.app\" \"${QT_PLUGINS}\" \"${DIRS}\")")
endif()
if (UNIX AND NOT APPLE)
if (UNIX AND NOT APPLE AND NOT HAIKU)
find_package(X11 REQUIRED)
target_link_libraries(ui PRIVATE X11::X11 X11::Xi)
target_sources(ui PRIVATE xinput2_mouse.cpp)

View File

@@ -162,6 +162,8 @@ int main(int argc, char* argv[]) {
{
return 0;
}
fprintf(stderr, "Qt: version %s, platform \"%s\"\n", qVersion(), QApplication::platformName().toUtf8().data());
ProgSettings::loadTranslators(&app);
#ifdef Q_OS_WINDOWS
auto font_name = QObject::tr("FONT_NAME");

View File

@@ -72,7 +72,7 @@ extern "C" {
#include "qt_mediamenu.hpp"
#include "qt_util.hpp"
#ifdef __unix__
#if defined __unix__ && !defined __HAIKU__
#ifdef WAYLAND
#include "wl_mouse.hpp"
#endif
@@ -82,6 +82,32 @@ extern "C" {
#undef KeyRelease
#endif
#ifdef __HAIKU__
#include <os/AppKit.h>
#include <os/InterfaceKit.h>
extern MainWindow* main_window;
filter_result keyb_filter(BMessage *message, BHandler **target, BMessageFilter *filter)
{
if (message->what == B_KEY_DOWN || message->what == B_KEY_UP
|| message->what == B_UNMAPPED_KEY_DOWN || message->what == B_UNMAPPED_KEY_UP)
{
int key_state = 0, key_scancode = 0;
key_state = message->what == B_KEY_DOWN || message->what == B_UNMAPPED_KEY_DOWN;
message->FindInt32("key", &key_scancode);
QGuiApplication::postEvent(main_window, new QKeyEvent(key_state ? QEvent::KeyPress : QEvent::KeyRelease, 0, QGuiApplication::keyboardModifiers(), key_scancode, 0, 0));
if (key_scancode == 0x68 && key_state)
{
QGuiApplication::postEvent(main_window, new QKeyEvent(QEvent::KeyRelease, 0, QGuiApplication::keyboardModifiers(), key_scancode, 0, 0));
}
}
return B_DISPATCH_MESSAGE;
}
static BMessageFilter* filter;
#endif
extern void qt_mouse_capture(int);
extern "C" void qt_blit(int x, int y, int w, int h);
@@ -93,6 +119,10 @@ MainWindow::MainWindow(QWidget *parent) :
MediaMenu::ptr = mm;
status = std::make_unique<MachineStatus>(this);
#ifdef __HAIKU__
filter = new BMessageFilter(B_PROGRAMMED_DELIVERY, B_ANY_SOURCE, keyb_filter);
((BWindow*)this->winId())->AddFilter(filter);
#endif
setUnifiedTitleAndToolBarOnMac(true);
ui->setupUi(this);
ui->stackedWidget->setMouseTracking(true);
@@ -234,9 +264,12 @@ MainWindow::MainWindow(QWidget *parent) :
ui->actionHardware_Renderer_OpenGL->setVisible(QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGLES);
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES && vid_api == 1) vid_api = 0;
if (QApplication::platformName().contains("eglfs") && vid_api >= 1) {
fprintf(stderr, "OpenGL renderers are unsupported on EGLFS.\n");
if ((QApplication::platformName().contains("eglfs") || QApplication::platformName() == "haiku")) {
if (vid_api >= 1) fprintf(stderr, "OpenGL renderers are unsupported on %s.\n", QApplication::platformName().toUtf8().data());
vid_api = 0;
ui->actionHardware_Renderer_OpenGL->setVisible(false);
ui->actionHardware_Renderer_OpenGL_ES->setVisible(false);
ui->actionOpenGL_3_0_Core->setVisible(false);
}
QActionGroup* actGroup = nullptr;
@@ -464,7 +497,7 @@ void MainWindow::closeEvent(QCloseEvent *event) {
}
qt_nvr_save();
config_save();
#ifdef __unix__
#if defined __unix__ && !defined __HAIKU__
extern void xinput2_exit();
if (QApplication::platformName() == "xcb") xinput2_exit();
#endif
@@ -1054,6 +1087,117 @@ static std::unordered_map<uint32_t, uint16_t> evdev_to_xt =
{111, 0x153}
};
#ifdef __HAIKU__
static std::unordered_map<uint8_t, uint16_t> be_to_xt =
{
{0x01, 0x01},
{B_F1_KEY, 0x3B},
{B_F2_KEY, 0x3C},
{B_F3_KEY, 0x3D},
{B_F4_KEY, 0x3E},
{B_F5_KEY, 0x3F},
{B_F6_KEY, 0x40},
{B_F7_KEY, 0x41},
{B_F8_KEY, 0x42},
{B_F9_KEY, 0x43},
{B_F10_KEY, 0x44},
{B_F11_KEY, 0x57},
{B_F12_KEY, 0x58},
{0x11, 0x29},
{0x12, 0x02},
{0x13, 0x03},
{0x14, 0x04},
{0x15, 0x05},
{0x16, 0x06},
{0x17, 0x07},
{0x18, 0x08},
{0x19, 0x09},
{0x1A, 0x0A},
{0x1B, 0x0B},
{0x1C, 0x0C},
{0x1D, 0x0D},
{0x1E, 0x0E},
{0x1F, 0x152},
{0x20, 0x147},
{0x21, 0x149},
{0x22, 0x45},
{0x23, 0x135},
{0x24, 0x37},
{0x25, 0x4A},
{0x26, 0x0F},
{0x27, 0x10},
{0x28, 0x11},
{0x29, 0x12},
{0x2A, 0x13},
{0x2B, 0x14},
{0x2C, 0x15},
{0x2D, 0x16},
{0x2E, 0x17},
{0x2F, 0x18},
{0x30, 0x19},
{0x31, 0x1A},
{0x32, 0x1B},
{0x33, 0x2B},
{0x34, 0x153},
{0x35, 0x14F},
{0x36, 0x151},
{0x37, 0x47},
{0x38, 0x48},
{0x39, 0x49},
{0x3A, 0x4E},
{0x3B, 0x3A},
{0x3C, 0x1E},
{0x3D, 0x1F},
{0x3E, 0x20},
{0x3F, 0x21},
{0x40, 0x22},
{0x41, 0x23},
{0x42, 0x24},
{0x43, 0x25},
{0x44, 0x26},
{0x45, 0x27},
{0x46, 0x28},
{0x47, 0x1C},
{0x48, 0x4B},
{0x49, 0x4C},
{0x4A, 0x4D},
{0x4B, 0x2A},
{0x4C, 0x2C},
{0x4D, 0x2D},
{0x4E, 0x2E},
{0x4F, 0x2F},
{0x50, 0x30},
{0x51, 0x31},
{0x52, 0x32},
{0x53, 0x33},
{0x54, 0x34},
{0x55, 0x35},
{0x56, 0x36},
{0x57, 0x148},
{0x58, 0x51},
{0x59, 0x50},
{0x5A, 0x4F},
{0x5B, 0x11C},
{0x5C, 0x1D},
{0x5D, 0x38},
{0x5E, 0x39},
{0x5F, 0x138},
{0x60, 0x11D},
{0x61, 0x14B},
{0x62, 0x150},
{0x63, 0x14D},
{0x64, 0x52},
{0x65, 0x53},
{0x0e, 0x137},
{0x0f, 0x46},
{0x66, 0x15B},
{0x67, 0x15C},
{0x68, 0x15D},
{0x69, 0x56}
};
#endif
static std::array<uint32_t, 256>& selected_keycode = x11_to_xt_base;
uint16_t x11_keycode_to_keysym(uint32_t keycode)
@@ -1063,6 +1207,8 @@ uint16_t x11_keycode_to_keysym(uint32_t keycode)
finalkeycode = (keycode & 0xFFFF);
#elif defined(__APPLE__)
finalkeycode = darwin_to_xt[keycode];
#elif defined(__HAIKU__)
finalkeycode = be_to_xt[keycode];
#else
static Display* x11display = nullptr;
if (QApplication::platformName().contains("wayland"))

View File

@@ -49,7 +49,7 @@ RendererStack::RendererStack(QWidget *parent)
{
ui->setupUi(this);
#ifdef __unix__
#if defined __unix__ && !defined __HAIKU__
# ifdef WAYLAND
if (QApplication::platformName().contains("wayland")) {
wl_init();
@@ -104,7 +104,7 @@ RendererStack::mousePoll()
mousedata.deltax = mousedata.deltay = mousedata.deltaz = 0;
mouse_buttons = mousedata.mousebuttons;
# ifdef __unix__
# if defined __unix__ && !defined __HAIKU__
# ifdef WAYLAND
if (QApplication::platformName().contains("wayland"))
wl_mouse_poll();
@@ -206,6 +206,7 @@ RendererStack::leaveEvent(QEvent *event)
}
if (!mouse_capture)
return;
QCursor::setPos(mapToGlobal(QPoint(width() / 2, height() / 2)));
ignoreNextMouseEvent = 2;
event->accept();
}
@@ -237,7 +238,11 @@ RendererStack::createRenderer(Renderer renderer)
auto sw = new SoftwareRenderer(this);
rendererWindow = sw;
connect(this, &RendererStack::blitToRenderer, sw, &SoftwareRenderer::onBlit, Qt::QueuedConnection);
#ifdef __HAIKU__
current.reset(sw);
#else
current.reset(this->createWindowContainer(sw, this));
#endif
}
break;
case Renderer::OpenGL:

View File

@@ -28,9 +28,13 @@ extern "C" {
}
SoftwareRenderer::SoftwareRenderer(QWidget *parent)
#ifdef __HAIKU__
: QWidget(parent)
#else
: QRasterWindow(parent->windowHandle())
#endif
{
parentWidget = parent;
RendererCommon::parentWidget = parent;
images[0] = std::make_unique<QImage>(QSize(2048, 2048), QImage::Format_RGB32);
images[1] = std::make_unique<QImage>(QSize(2048, 2048), QImage::Format_RGB32);
@@ -38,6 +42,9 @@ SoftwareRenderer::SoftwareRenderer(QWidget *parent)
buf_usage = std::vector<std::atomic_flag>(2);
buf_usage[0].clear();
buf_usage[1].clear();
#ifdef __HAIKU__
this->setMouseTracking(true);
#endif
}
void SoftwareRenderer::paintEvent(QPaintEvent* event) {
@@ -60,13 +67,22 @@ void SoftwareRenderer::onBlit(int buf_idx, int x, int y, int w, int h) {
void SoftwareRenderer::resizeEvent(QResizeEvent *event) {
onResize(width(), height());
#ifdef __HAIKU__
QWidget::resizeEvent(event);
#else
QRasterWindow::resizeEvent(event);
#endif
}
bool SoftwareRenderer::event(QEvent *event)
{
bool res = false;
if (!eventDelegate(event, res)) return QRasterWindow::event(event);
if (!eventDelegate(event, res))
#ifdef __HAIKU__
return QWidget::event(event);
#else
return QRasterWindow::event(event);
#endif
return res;
}

View File

@@ -8,7 +8,13 @@
#include <atomic>
#include "qt_renderercommon.hpp"
class SoftwareRenderer : public QRasterWindow, public RendererCommon
class SoftwareRenderer :
#ifdef __HAIKU__
public QWidget,
#else
public QRasterWindow,
#endif
public RendererCommon
{
Q_OBJECT
public:

View File

@@ -62,6 +62,10 @@ else()
endif()
endif()
if(SYSTEM_MIDI)
target_compile_definition(snd PRIVATE SYSTEM_MIDI)
endif()
if(FLUIDSYNTH)
target_compile_definitions(snd PRIVATE USE_FLUIDSYNTH)
target_sources(snd PRIVATE midi_fluidsynth.c)

View File

@@ -13,12 +13,15 @@
* Copyright 2021 Cacodemon345.
* Copyright 2021 Miran Grca.
*/
#if defined __has_include
# if __has_include (<RtMidi.h>)
# include <RtMidi.h>
# endif
# if __has_include (<rtmidi/RtMidi.h>)
# include <rtmidi/RtMidi.h>
#ifdef SYSTEM_MIDI
# if defined __has_include
# if __has_include (<RtMidi.h>)
# include <RtMidi.h>
# endif
# if __has_include (<rtmidi/RtMidi.h>)
# include <rtmidi/RtMidi.h>
# endif
# endif
#endif
@@ -35,9 +38,10 @@ extern "C"
#include <86box/midi_rtmidi.h>
#include <86box/config.h>
#ifdef SYSTEM_MIDI
static RtMidiOut * midiout = nullptr;
static RtMidiIn * midiin = nullptr;
#endif
static int midi_out_id = 0, midi_in_id = 0;
static const int midi_lengths[8] = {3, 3, 3, 3, 2, 2, 3, 1};
@@ -49,6 +53,7 @@ rtmidi_write(uint8_t val)
}
#ifdef SYSTEM_MIDI
void
rtmidi_play_msg(uint8_t *msg)
{
@@ -231,6 +236,76 @@ rtmidi_in_get_dev_name(int num, char *s)
{
strcpy(s, midiin->getPortName(num).c_str());
}
#else /* !SYSTEM_MIDI */
void
rtmidi_play_msg(uint8_t *msg)
{
}
void
rtmidi_play_sysex(uint8_t *sysex, unsigned int len)
{
}
void*
rtmidi_init(const device_t *info)
{
return nullptr;
}
void
rtmidi_close(void *p)
{
}
int
rtmidi_get_num_devs(void)
{
return 0;
}
void
rtmidi_get_dev_name(int num, char *s)
{
}
void*
rtmidi_input_init(const device_t *info)
{
return nullptr;
}
void
rtmidi_input_close(void* p)
{
}
int
rtmidi_in_get_num_devs(void)
{
return 0;
}
void
rtmidi_in_get_dev_name(int num, char *s)
{
}
#endif
static const device_config_t system_midi_config[] =
{

View File

@@ -27,4 +27,4 @@ target_link_libraries(86Box Threads::Threads)
add_library(ui OBJECT unix_sdl.c unix_cdrom.c)
target_compile_definitions(ui PUBLIC _FILE_OFFSET_BITS=64)
target_link_libraries(ui dl)
target_link_libraries(ui ${CMAKE_DL_LIBS})