Initial Qt Commit
This commit is contained in:
parent
81a49c8c5c
commit
c587a02b1a
@ -60,6 +60,7 @@ option(MUNT "MUNT" ON)
|
||||
option(VRAMDUMP "Video RAM dumping" OFF)
|
||||
option(DINPUT "DirectInput" OFF)
|
||||
option(DISCORD "Discord integration" ON)
|
||||
option(QT "QT GUI" ON)
|
||||
|
||||
option(NEW_DYNAREC "Use the PCem v15 (\"new\") dynamic recompiler" OFF)
|
||||
|
||||
|
@ -221,7 +221,10 @@ add_subdirectory(sio)
|
||||
add_subdirectory(scsi)
|
||||
add_subdirectory(sound)
|
||||
add_subdirectory(video)
|
||||
if(APPLE)
|
||||
|
||||
if (QT)
|
||||
add_subdirectory(qt)
|
||||
elseif(APPLE)
|
||||
add_subdirectory(mac)
|
||||
add_subdirectory(unix)
|
||||
elseif(WIN32)
|
||||
|
86
src/qt/CMakeLists.txt
Normal file
86
src/qt/CMakeLists.txt
Normal file
@ -0,0 +1,86 @@
|
||||
find_package(Qt5 COMPONENTS Core Widgets REQUIRED)
|
||||
|
||||
# Find includes in corresponding build directories
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
add_library(plat STATIC qt.c qt_main.cpp qt_platform.cpp qt_midi.cpp cpp11_thread.cpp)
|
||||
add_library(ui STATIC
|
||||
qt_ui.cpp
|
||||
qt_cdrom.c
|
||||
qt_sdl.c
|
||||
|
||||
qt_mainwindow.cpp
|
||||
qt_mainwindow.hpp
|
||||
qt_mainwindow.ui
|
||||
|
||||
qt_settings.cpp
|
||||
qt_settings.hpp
|
||||
qt_settings.ui
|
||||
|
||||
qt_settingsmachine.cpp
|
||||
qt_settingsmachine.hpp
|
||||
qt_settingsmachine.ui
|
||||
qt_settingsdisplay.cpp
|
||||
qt_settingsdisplay.hpp
|
||||
qt_settingsdisplay.ui
|
||||
qt_settingsinput.cpp
|
||||
qt_settingsinput.hpp
|
||||
qt_settingsinput.ui
|
||||
qt_settingssound.cpp
|
||||
qt_settingssound.hpp
|
||||
qt_settingssound.ui
|
||||
qt_settingsnetwork.cpp
|
||||
qt_settingsnetwork.hpp
|
||||
qt_settingsnetwork.ui
|
||||
qt_settingsports.cpp
|
||||
qt_settingsports.hpp
|
||||
qt_settingsports.ui
|
||||
qt_settingsstoragecontrollers.cpp
|
||||
qt_settingsstoragecontrollers.hpp
|
||||
qt_settingsstoragecontrollers.ui
|
||||
qt_settingsharddisks.cpp
|
||||
qt_settingsharddisks.hpp
|
||||
qt_settingsharddisks.ui
|
||||
qt_settingsfloppycdrom.cpp
|
||||
qt_settingsfloppycdrom.hpp
|
||||
qt_settingsfloppycdrom.ui
|
||||
qt_settingsotherremovable.cpp
|
||||
qt_settingsotherremovable.hpp
|
||||
qt_settingsotherremovable.ui
|
||||
qt_settingsotherperipherals.cpp
|
||||
qt_settingsotherperipherals.hpp
|
||||
qt_settingsotherperipherals.ui
|
||||
|
||||
qt_deviceconfig.cpp
|
||||
qt_deviceconfig.hpp
|
||||
qt_deviceconfig.ui
|
||||
|
||||
qt_filefield.cpp
|
||||
qt_filefield.hpp
|
||||
qt_filefield.ui
|
||||
qt_harddiskdialog.cpp
|
||||
qt_harddiskdialog.hpp
|
||||
qt_harddiskdialog.ui
|
||||
|
||||
qt_harddrive_common.cpp
|
||||
qt_harddrive_common.hpp
|
||||
qt_models_common.cpp
|
||||
qt_models_common.hpp
|
||||
|
||||
../qt_resources.qrc
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
plat
|
||||
PRIVATE
|
||||
Qt5::Widgets
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
ui
|
||||
PRIVATE
|
||||
Qt5::Widgets
|
||||
)
|
1
src/qt/TODO
Normal file
1
src/qt/TODO
Normal file
@ -0,0 +1 @@
|
||||
* Joystick support
|
130
src/qt/cpp11_thread.cpp
Normal file
130
src/qt/cpp11_thread.cpp
Normal file
@ -0,0 +1,130 @@
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
|
||||
#include <86box/plat.h>
|
||||
|
||||
struct event_cpp11_t
|
||||
{
|
||||
std::condition_variable cond;
|
||||
std::mutex mutex;
|
||||
std::atomic_bool state = false;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
thread_t *
|
||||
thread_create(void (*thread_rout)(void *param), void *param)
|
||||
{
|
||||
auto thread = new std::thread([thread_rout, param] {
|
||||
thread_rout(param);
|
||||
});
|
||||
return thread;
|
||||
}
|
||||
|
||||
mutex_t *
|
||||
thread_create_mutex_with_spin_count(unsigned int spin_count)
|
||||
{
|
||||
/* Setting spin count of a mutex is not possible with pthreads. */
|
||||
return thread_create_mutex();
|
||||
}
|
||||
|
||||
int
|
||||
thread_wait(thread_t *arg, int timeout)
|
||||
{
|
||||
(void) timeout;
|
||||
auto thread = reinterpret_cast<std::thread*>(arg);
|
||||
thread->join();
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_t *
|
||||
thread_create_mutex(void)
|
||||
{
|
||||
auto mutex = new std::mutex;
|
||||
return mutex;
|
||||
}
|
||||
|
||||
int
|
||||
thread_wait_mutex(mutex_t *_mutex)
|
||||
{
|
||||
if (_mutex == nullptr)
|
||||
return(0);
|
||||
auto mutex = reinterpret_cast<std::mutex*>(_mutex);
|
||||
mutex->lock();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
thread_release_mutex(mutex_t *_mutex)
|
||||
{
|
||||
if (_mutex == nullptr)
|
||||
return(0);
|
||||
auto mutex = reinterpret_cast<std::mutex*>(_mutex);
|
||||
mutex->unlock();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
thread_close_mutex(mutex_t *_mutex)
|
||||
{
|
||||
auto mutex = reinterpret_cast<std::mutex*>(_mutex);
|
||||
delete mutex;
|
||||
}
|
||||
|
||||
event_t *
|
||||
thread_create_event()
|
||||
{
|
||||
auto ev = new event_cpp11_t;
|
||||
return ev;
|
||||
}
|
||||
|
||||
int
|
||||
thread_wait_event(event_t *handle, int timeout)
|
||||
{
|
||||
auto event = reinterpret_cast<event_cpp11_t*>(handle);
|
||||
auto lock = std::unique_lock<std::mutex>(event->mutex);
|
||||
|
||||
if (timeout < 0) {
|
||||
event->cond.wait(lock, [=] { return event->state.load(); });
|
||||
} else {
|
||||
auto to = std::chrono::system_clock::now() + std::chrono::milliseconds(timeout);
|
||||
std::cv_status status;
|
||||
|
||||
do {
|
||||
status = event->cond.wait_until(lock, to);
|
||||
} while ((status != std::cv_status::timeout) && !event->state);
|
||||
|
||||
if (status == std::cv_status::timeout) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
thread_set_event(event_t *handle)
|
||||
{
|
||||
auto event = reinterpret_cast<event_cpp11_t*>(handle);
|
||||
event->state = true;
|
||||
event->cond.notify_all();
|
||||
}
|
||||
|
||||
void
|
||||
thread_reset_event(event_t *handle)
|
||||
{
|
||||
auto event = reinterpret_cast<event_cpp11_t*>(handle);
|
||||
event->state = false;
|
||||
}
|
||||
|
||||
void
|
||||
thread_destroy_event(event_t *handle)
|
||||
{
|
||||
auto event = reinterpret_cast<event_cpp11_t*>(handle);
|
||||
delete event;
|
||||
}
|
||||
|
||||
}
|
70
src/qt/qt.c
Normal file
70
src/qt/qt.c
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* C functionality for Qt platform, where the C equivalent is not easily
|
||||
* implemented in Qt
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/nvr.h>
|
||||
|
||||
#include "qt_sdl.h"
|
||||
|
||||
int qt_nvr_save(void) {
|
||||
return nvr_save();
|
||||
}
|
||||
|
||||
char icon_set[256] = ""; /* name of the iconset to be used */
|
||||
|
||||
wchar_t* plat_get_string(int i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case IDS_2077:
|
||||
return L"Click to capture mouse.";
|
||||
case IDS_2078:
|
||||
return L"Press CTRL-END to release mouse";
|
||||
case IDS_2079:
|
||||
return L"Press CTRL-END or middle button to release mouse";
|
||||
case IDS_2080:
|
||||
return L"Failed to initialize FluidSynth";
|
||||
case IDS_4099:
|
||||
return L"MFM/RLL or ESDI CD-ROM drives never existed";
|
||||
case IDS_2093:
|
||||
return L"Failed to set up PCap";
|
||||
case IDS_2094:
|
||||
return L"No PCap devices found";
|
||||
case IDS_2110:
|
||||
return L"Unable to initialize FreeType";
|
||||
case IDS_2111:
|
||||
return L"Unable to initialize SDL, libsdl2 is required";
|
||||
case IDS_2131:
|
||||
return L"libfreetype is required for ESC/P printer emulation.";
|
||||
case IDS_2132:
|
||||
return L"libgs 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.";
|
||||
case IDS_2129:
|
||||
return L"Make sure libpcap is installed and that you are on a libpcap-compatible network connection.";
|
||||
case IDS_2114:
|
||||
return L"Unable to initialize Ghostscript";
|
||||
case IDS_2063:
|
||||
return L"Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine.";
|
||||
case IDS_2064:
|
||||
return L"Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card.";
|
||||
case IDS_2128:
|
||||
return L"Hardware not available";
|
||||
}
|
||||
return L"";
|
||||
}
|
||||
|
||||
int
|
||||
plat_vidapi(char* api) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* plat_vidapi_name(int api) {
|
||||
return "default";
|
||||
}
|
264
src/qt/qt_cdrom.c
Normal file
264
src/qt/qt_cdrom.c
Normal file
@ -0,0 +1,264 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Handle the platform-side of CDROM/ZIP/MO drives.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2017,2018 Fred N. van Kempen.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/config.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/cassette.h>
|
||||
#include <86box/cartridge.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/hdd.h>
|
||||
#include <86box/scsi_device.h>
|
||||
#include <86box/cdrom.h>
|
||||
#include <86box/mo.h>
|
||||
#include <86box/zip.h>
|
||||
#include <86box/scsi_disk.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/ui.h>
|
||||
|
||||
|
||||
|
||||
void
|
||||
cassette_mount(char *fn, uint8_t wp)
|
||||
{
|
||||
pc_cas_set_fname(cassette, NULL);
|
||||
memset(cassette_fname, 0, sizeof(cassette_fname));
|
||||
cassette_ui_writeprot = wp;
|
||||
pc_cas_set_fname(cassette, fn);
|
||||
if (fn != NULL)
|
||||
memcpy(cassette_fname, fn, MIN(511, strlen(fn)));
|
||||
ui_sb_update_icon_state(SB_CASSETTE, (fn == NULL) ? 1 : 0);
|
||||
//media_menu_update_cassette();
|
||||
ui_sb_update_tip(SB_CASSETTE);
|
||||
config_save();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cassette_eject(void)
|
||||
{
|
||||
pc_cas_set_fname(cassette, NULL);
|
||||
memset(cassette_fname, 0x00, sizeof(cassette_fname));
|
||||
ui_sb_update_icon_state(SB_CASSETTE, 1);
|
||||
//media_menu_update_cassette();
|
||||
ui_sb_update_tip(SB_CASSETTE);
|
||||
config_save();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cartridge_mount(uint8_t id, char *fn, uint8_t wp)
|
||||
{
|
||||
cart_close(id);
|
||||
cart_load(id, fn);
|
||||
ui_sb_update_icon_state(SB_CARTRIDGE | id, strlen(cart_fns[id]) ? 0 : 1);
|
||||
//media_menu_update_cartridge(id);
|
||||
ui_sb_update_tip(SB_CARTRIDGE | id);
|
||||
config_save();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
cartridge_eject(uint8_t id)
|
||||
{
|
||||
cart_close(id);
|
||||
ui_sb_update_icon_state(SB_CARTRIDGE | id, 1);
|
||||
//media_menu_update_cartridge(id);
|
||||
ui_sb_update_tip(SB_CARTRIDGE | id);
|
||||
config_save();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
floppy_mount(uint8_t id, char *fn, uint8_t wp)
|
||||
{
|
||||
fdd_close(id);
|
||||
ui_writeprot[id] = wp;
|
||||
fdd_load(id, fn);
|
||||
ui_sb_update_icon_state(SB_FLOPPY | id, strlen(floppyfns[id]) ? 0 : 1);
|
||||
//media_menu_update_floppy(id);
|
||||
ui_sb_update_tip(SB_FLOPPY | id);
|
||||
config_save();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
floppy_eject(uint8_t id)
|
||||
{
|
||||
fdd_close(id);
|
||||
ui_sb_update_icon_state(SB_FLOPPY | id, 1);
|
||||
//media_menu_update_floppy(id);
|
||||
ui_sb_update_tip(SB_FLOPPY | id);
|
||||
config_save();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
plat_cdrom_ui_update(uint8_t id, uint8_t reload)
|
||||
{
|
||||
cdrom_t *drv = &cdrom[id];
|
||||
|
||||
if (drv->host_drive == 0) {
|
||||
ui_sb_update_icon_state(SB_CDROM|id, 1);
|
||||
} else {
|
||||
ui_sb_update_icon_state(SB_CDROM|id, 0);
|
||||
}
|
||||
|
||||
//media_menu_update_cdrom(id);
|
||||
ui_sb_update_tip(SB_CDROM|id);
|
||||
}
|
||||
|
||||
void
|
||||
cdrom_mount(uint8_t id, char *fn)
|
||||
{
|
||||
cdrom[id].prev_host_drive = cdrom[id].host_drive;
|
||||
strcpy(cdrom[id].prev_image_path, cdrom[id].image_path);
|
||||
if (cdrom[id].ops && cdrom[id].ops->exit)
|
||||
cdrom[id].ops->exit(&(cdrom[id]));
|
||||
cdrom[id].ops = NULL;
|
||||
memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path));
|
||||
cdrom_image_open(&(cdrom[id]), fn);
|
||||
/* Signal media change to the emulated machine. */
|
||||
if (cdrom[id].insert)
|
||||
cdrom[id].insert(cdrom[id].priv);
|
||||
cdrom[id].host_drive = (strlen(cdrom[id].image_path) == 0) ? 0 : 200;
|
||||
if (cdrom[id].host_drive == 200) {
|
||||
ui_sb_update_icon_state(SB_CDROM | id, 0);
|
||||
} else {
|
||||
ui_sb_update_icon_state(SB_CDROM | id, 1);
|
||||
}
|
||||
//media_menu_update_cdrom(id);
|
||||
ui_sb_update_tip(SB_CDROM | id);
|
||||
config_save();
|
||||
}
|
||||
|
||||
void
|
||||
mo_eject(uint8_t id)
|
||||
{
|
||||
mo_t *dev = (mo_t *) mo_drives[id].priv;
|
||||
|
||||
mo_disk_close(dev);
|
||||
if (mo_drives[id].bus_type) {
|
||||
/* Signal disk change to the emulated machine. */
|
||||
mo_insert(dev);
|
||||
}
|
||||
|
||||
ui_sb_update_icon_state(SB_MO | id, 1);
|
||||
//media_menu_update_mo(id);
|
||||
ui_sb_update_tip(SB_MO | id);
|
||||
config_save();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mo_mount(uint8_t id, char *fn, uint8_t wp)
|
||||
{
|
||||
mo_t *dev = (mo_t *) mo_drives[id].priv;
|
||||
|
||||
mo_disk_close(dev);
|
||||
mo_drives[id].read_only = wp;
|
||||
mo_load(dev, fn);
|
||||
mo_insert(dev);
|
||||
|
||||
ui_sb_update_icon_state(SB_MO | id, strlen(mo_drives[id].image_path) ? 0 : 1);
|
||||
//media_menu_update_mo(id);
|
||||
ui_sb_update_tip(SB_MO | id);
|
||||
|
||||
config_save();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mo_reload(uint8_t id)
|
||||
{
|
||||
mo_t *dev = (mo_t *) mo_drives[id].priv;
|
||||
|
||||
mo_disk_reload(dev);
|
||||
if (strlen(mo_drives[id].image_path) == 0) {
|
||||
ui_sb_update_icon_state(SB_MO|id, 1);
|
||||
} else {
|
||||
ui_sb_update_icon_state(SB_MO|id, 0);
|
||||
}
|
||||
|
||||
//media_menu_update_mo(id);
|
||||
ui_sb_update_tip(SB_MO|id);
|
||||
|
||||
config_save();
|
||||
}
|
||||
|
||||
void
|
||||
zip_eject(uint8_t id)
|
||||
{
|
||||
zip_t *dev = (zip_t *) zip_drives[id].priv;
|
||||
|
||||
zip_disk_close(dev);
|
||||
if (zip_drives[id].bus_type) {
|
||||
/* Signal disk change to the emulated machine. */
|
||||
zip_insert(dev);
|
||||
}
|
||||
|
||||
ui_sb_update_icon_state(SB_ZIP | id, 1);
|
||||
//media_menu_update_zip(id);
|
||||
ui_sb_update_tip(SB_ZIP | id);
|
||||
config_save();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
zip_mount(uint8_t id, char *fn, uint8_t wp)
|
||||
{
|
||||
zip_t *dev = (zip_t *) zip_drives[id].priv;
|
||||
|
||||
zip_disk_close(dev);
|
||||
zip_drives[id].read_only = wp;
|
||||
zip_load(dev, fn);
|
||||
zip_insert(dev);
|
||||
|
||||
ui_sb_update_icon_state(SB_ZIP | id, strlen(zip_drives[id].image_path) ? 0 : 1);
|
||||
//media_menu_update_zip(id);
|
||||
ui_sb_update_tip(SB_ZIP | id);
|
||||
|
||||
config_save();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
zip_reload(uint8_t id)
|
||||
{
|
||||
zip_t *dev = (zip_t *) zip_drives[id].priv;
|
||||
|
||||
zip_disk_reload(dev);
|
||||
if (strlen(zip_drives[id].image_path) == 0) {
|
||||
ui_sb_update_icon_state(SB_ZIP|id, 1);
|
||||
} else {
|
||||
ui_sb_update_icon_state(SB_ZIP|id, 0);
|
||||
}
|
||||
|
||||
//media_menu_update_zip(id);
|
||||
ui_sb_update_tip(SB_ZIP|id);
|
||||
|
||||
config_save();
|
||||
}
|
157
src/qt/qt_deviceconfig.cpp
Normal file
157
src/qt/qt_deviceconfig.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
#include "qt_deviceconfig.hpp"
|
||||
#include "ui_qt_deviceconfig.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QComboBox>
|
||||
#include <QFormLayout>
|
||||
#include <QSpinBox>
|
||||
#include <QCheckBox>
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/config.h>
|
||||
#include <86box/device.h>
|
||||
}
|
||||
|
||||
#include "qt_filefield.hpp"
|
||||
|
||||
DeviceConfig::DeviceConfig(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::DeviceConfig)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
DeviceConfig::~DeviceConfig()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void DeviceConfig::ConfigureDevice(const _device_* device) {
|
||||
DeviceConfig dc;
|
||||
dc.setWindowTitle(QString("%1 Device Configuration").arg(device->name));
|
||||
|
||||
device_context_t device_context;
|
||||
device_set_context(&device_context, device, 0);
|
||||
|
||||
const auto* config = device->config;
|
||||
while (config->type != -1) {
|
||||
switch (config->type) {
|
||||
case CONFIG_BINARY:
|
||||
{
|
||||
auto value = config_get_int(device_context.name, const_cast<char*>(config->name), config->default_int);
|
||||
auto* cbox = new QCheckBox();
|
||||
cbox->setObjectName(config->name);
|
||||
cbox->setChecked(value > 0);
|
||||
dc.ui->formLayout->addRow(config->description, cbox);
|
||||
break;
|
||||
}
|
||||
case CONFIG_SELECTION:
|
||||
case CONFIG_MIDI:
|
||||
case CONFIG_MIDI_IN:
|
||||
case CONFIG_HEX16:
|
||||
case CONFIG_HEX20:
|
||||
{
|
||||
auto* cbox = new QComboBox();
|
||||
cbox->setObjectName(config->name);
|
||||
auto* model = cbox->model();
|
||||
int currentIndex = -1;
|
||||
int selected = config_get_int(device_context.name, const_cast<char*>(config->name), config->default_int);
|
||||
|
||||
for (auto* sel = config->selection; (sel->description != nullptr) && (strlen(sel->description) > 0); ++sel) {
|
||||
int rows = model->rowCount();
|
||||
model->insertRow(rows);
|
||||
auto idx = model->index(rows, 0);
|
||||
|
||||
model->setData(idx, sel->description, Qt::DisplayRole);
|
||||
model->setData(idx, sel->value, Qt::UserRole);
|
||||
|
||||
if (selected == sel->value) {
|
||||
currentIndex = idx.row();
|
||||
}
|
||||
}
|
||||
|
||||
dc.ui->formLayout->addRow(config->description, cbox);
|
||||
cbox->setCurrentIndex(currentIndex);
|
||||
break;
|
||||
}
|
||||
case CONFIG_SPINNER:
|
||||
{
|
||||
int value = config_get_int(device_context.name, const_cast<char*>(config->name), config->default_int);
|
||||
auto* spinBox = new QSpinBox();
|
||||
spinBox->setObjectName(config->name);
|
||||
spinBox->setMaximum(config->spinner.max);
|
||||
spinBox->setMinimum(config->spinner.min);
|
||||
if (config->spinner.step > 0) {
|
||||
spinBox->setSingleStep(config->spinner.step);
|
||||
}
|
||||
spinBox->setValue(value);
|
||||
dc.ui->formLayout->addRow(config->description, spinBox);
|
||||
break;
|
||||
}
|
||||
case CONFIG_FNAME:
|
||||
{
|
||||
auto* fileName = config_get_string(device_context.name, const_cast<char*>(config->name), const_cast<char*>(config->default_string));
|
||||
auto* fileField = new FileField();
|
||||
fileField->setObjectName(config->name);
|
||||
fileField->setFileName(fileName);
|
||||
dc.ui->formLayout->addRow(config->description, fileField);
|
||||
break;
|
||||
}
|
||||
}
|
||||
++config;
|
||||
}
|
||||
|
||||
int res = dc.exec();
|
||||
if (res == QDialog::Accepted) {
|
||||
config = device->config;
|
||||
while (config->type != -1) {
|
||||
switch (config->type) {
|
||||
case CONFIG_BINARY:
|
||||
{
|
||||
auto* cbox = dc.findChild<QCheckBox*>(config->name);
|
||||
config_set_int(device_context.name, const_cast<char*>(config->name), cbox->isChecked() ? 1 : 0);
|
||||
break;
|
||||
}
|
||||
case CONFIG_SELECTION:
|
||||
case CONFIG_MIDI:
|
||||
case CONFIG_MIDI_IN:
|
||||
case CONFIG_HEX16:
|
||||
case CONFIG_HEX20:
|
||||
{
|
||||
auto* cbox = dc.findChild<QComboBox*>(config->name);
|
||||
config_set_int(device_context.name, const_cast<char*>(config->name), cbox->currentData().toInt());
|
||||
break;
|
||||
}
|
||||
case CONFIG_FNAME:
|
||||
{
|
||||
auto* fbox = dc.findChild<FileField*>(config->name);
|
||||
auto fileName = fbox->fileName().toUtf8();
|
||||
config_set_string(device_context.name, const_cast<char*>(config->name), fileName.data());
|
||||
break;
|
||||
}
|
||||
case CONFIG_SPINNER:
|
||||
{
|
||||
auto* spinBox = dc.findChild<QSpinBox*>(config->name);
|
||||
config_set_int(device_context.name, const_cast<char*>(config->name), spinBox->value());
|
||||
break;
|
||||
}
|
||||
}
|
||||
config++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString DeviceConfig::DeviceName(const _device_* device, const char *internalName, int bus) {
|
||||
if (QStringLiteral("none") == internalName) {
|
||||
return "None";
|
||||
} else if (QStringLiteral("internal") == internalName) {
|
||||
return "Internal";
|
||||
} else if (device == nullptr) {
|
||||
return QString();
|
||||
} else {
|
||||
char temp[512];
|
||||
device_get_name(device, bus, temp);
|
||||
return temp;
|
||||
}
|
||||
}
|
28
src/qt/qt_deviceconfig.hpp
Normal file
28
src/qt/qt_deviceconfig.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef QT_DEVICECONFIG_HPP
|
||||
#define QT_DEVICECONFIG_HPP
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
extern "C" {
|
||||
struct _device_;
|
||||
}
|
||||
|
||||
namespace Ui {
|
||||
class DeviceConfig;
|
||||
}
|
||||
|
||||
class DeviceConfig : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DeviceConfig(QWidget *parent = nullptr);
|
||||
~DeviceConfig();
|
||||
|
||||
static void ConfigureDevice(const _device_* device);
|
||||
static QString DeviceName(const _device_* device, const char* internalName, int bus);
|
||||
private:
|
||||
Ui::DeviceConfig *ui;
|
||||
};
|
||||
|
||||
#endif // QT_DEVICECONFIG_HPP
|
74
src/qt/qt_deviceconfig.ui
Normal file
74
src/qt/qt_deviceconfig.ui
Normal file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DeviceConfig</class>
|
||||
<widget class="QDialog" name="DeviceConfig">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>DeviceConfig</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>DeviceConfig</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
34
src/qt/qt_filefield.cpp
Normal file
34
src/qt/qt_filefield.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "qt_filefield.hpp"
|
||||
#include "ui_qt_filefield.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
FileField::FileField(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::FileField)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
FileField::~FileField()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void FileField::setFileName(const QString &fileName) {
|
||||
fileName_ = fileName;
|
||||
ui->label->setText(fileName);
|
||||
}
|
||||
|
||||
void FileField::on_pushButton_clicked() {
|
||||
QString fileName;
|
||||
if (createFile_) {
|
||||
fileName = QFileDialog::getSaveFileName(this, "Create...");
|
||||
} else {
|
||||
fileName = QFileDialog::getOpenFileName(this, "Open...");
|
||||
}
|
||||
|
||||
fileName_ = fileName;
|
||||
ui->label->setText(fileName);
|
||||
emit fileSelected(fileName);
|
||||
}
|
35
src/qt/qt_filefield.hpp
Normal file
35
src/qt/qt_filefield.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef QT_FILEFIELD_HPP
|
||||
#define QT_FILEFIELD_HPP
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class FileField;
|
||||
}
|
||||
|
||||
class FileField : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FileField(QWidget *parent = nullptr);
|
||||
~FileField();
|
||||
|
||||
QString fileName() const { return fileName_; }
|
||||
void setFileName(const QString& fileName);
|
||||
|
||||
void setCreateFile(bool createFile) { createFile_ = createFile; }
|
||||
|
||||
signals:
|
||||
void fileSelected(const QString& fileName);
|
||||
|
||||
private slots:
|
||||
void on_pushButton_clicked();
|
||||
|
||||
private:
|
||||
Ui::FileField *ui;
|
||||
QString fileName_;
|
||||
bool createFile_ = false;
|
||||
};
|
||||
|
||||
#endif // QT_FILEFIELD_HPP
|
47
src/qt/qt_filefield.ui
Normal file
47
src/qt/qt_filefield.ui
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>FileField</class>
|
||||
<widget class="QWidget" name="FileField">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="3,1">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
706
src/qt/qt_harddiskdialog.cpp
Normal file
706
src/qt/qt_harddiskdialog.cpp
Normal file
@ -0,0 +1,706 @@
|
||||
#include "qt_harddiskdialog.hpp"
|
||||
#include "ui_qt_harddiskdialog.h"
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/hdd.h>
|
||||
#include "../disk/minivhd/minivhd.h"
|
||||
#include "../disk/minivhd/minivhd_util.h"
|
||||
}
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QDebug>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QFileDialog>
|
||||
#include <QProgressDialog>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "qt_harddrive_common.hpp"
|
||||
#include "qt_models_common.hpp"
|
||||
|
||||
HarddiskDialog::HarddiskDialog(bool existing, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::HarddiskDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
if (existing) {
|
||||
setWindowTitle("Add Existing Hard Disk");
|
||||
ui->lineEditCylinders->setEnabled(false);
|
||||
ui->lineEditHeads->setEnabled(false);
|
||||
ui->lineEditSectors->setEnabled(false);
|
||||
ui->lineEditSize->setEnabled(false);
|
||||
ui->comboBoxType->setEnabled(false);
|
||||
|
||||
ui->comboBoxFormat->hide();
|
||||
ui->labelFormat->hide();
|
||||
|
||||
connect(ui->fileField, &FileField::fileSelected, this, &HarddiskDialog::onExistingFileSelected);
|
||||
} else {
|
||||
setWindowTitle("Add New Hard Disk");
|
||||
ui->fileField->setCreateFile(true);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &HarddiskDialog::onCreateNewFile);
|
||||
}
|
||||
|
||||
auto* model = ui->comboBoxFormat->model();
|
||||
model->insertRows(0, 6);
|
||||
model->setData(model->index(0, 0), "Raw image (.img)");
|
||||
model->setData(model->index(1, 0), "HDI image (.hdi)");
|
||||
model->setData(model->index(2, 0), "HDX image (.hdx)");
|
||||
model->setData(model->index(3, 0), "Fixed-size VHD (.vhd)");
|
||||
model->setData(model->index(4, 0), "Dynamic-size VHD (.vhd)");
|
||||
model->setData(model->index(5, 0), "Differencing VHD (.vhd)");
|
||||
|
||||
model = ui->comboBoxBlockSize->model();
|
||||
model->insertRows(0, 2);
|
||||
model->setData(model->index(0, 0), "Large blocks (2 MiB)");
|
||||
model->setData(model->index(1, 0), "Small blocks (512 KiB)");
|
||||
|
||||
ui->comboBoxBlockSize->hide();
|
||||
ui->labelBlockSize->hide();
|
||||
|
||||
Harddrives::populateBuses(ui->comboBoxBus->model());
|
||||
ui->comboBoxBus->setCurrentIndex(3);
|
||||
|
||||
model = ui->comboBoxType->model();
|
||||
for (int i = 0; i < 127; i++) {
|
||||
uint64_t size = ((uint64_t) hdd_table[i][0]) * hdd_table[i][1] * hdd_table[i][2];
|
||||
uint64_t size_mb = size >> 11LL;
|
||||
QString text = QString("%1 MiB (CHS: %2, %3, %4)").arg(size_mb).arg(hdd_table[i][0]).arg(hdd_table[i][1]).arg(hdd_table[i][2]);
|
||||
Models::AddEntry(model, text, i);
|
||||
}
|
||||
Models::AddEntry(model, "Custom...", 127);
|
||||
Models::AddEntry(model, "Custom (large)...", 128);
|
||||
|
||||
ui->lineEditSize->setValidator(new QIntValidator());
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
connect(ui->fileField, &FileField::fileSelected, this, [this] {
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
|
||||
});
|
||||
}
|
||||
|
||||
HarddiskDialog::~HarddiskDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
uint8_t HarddiskDialog::bus() const {
|
||||
return static_cast<uint8_t>(ui->comboBoxBus->currentData().toUInt());
|
||||
}
|
||||
|
||||
uint8_t HarddiskDialog::channel() const {
|
||||
return static_cast<uint8_t>(ui->comboBoxChannel->currentData().toUInt());
|
||||
}
|
||||
|
||||
QString HarddiskDialog::fileName() const {
|
||||
return ui->fileField->fileName();
|
||||
}
|
||||
|
||||
void HarddiskDialog::on_comboBoxFormat_currentIndexChanged(int index) {
|
||||
bool enabled;
|
||||
if (index == 5) { /* They switched to a diff VHD; disable the geometry fields. */
|
||||
enabled = false;
|
||||
ui->lineEditCylinders->setText(QStringLiteral("(N/A)"));
|
||||
ui->lineEditHeads->setText(QStringLiteral("(N/A)"));
|
||||
ui->lineEditSectors->setText(QStringLiteral("(N/A)"));
|
||||
ui->lineEditSize->setText(QStringLiteral("(N/A)"));
|
||||
} else {
|
||||
enabled = true;
|
||||
ui->lineEditCylinders->setText(QString::number(cylinders_));
|
||||
ui->lineEditHeads->setText(QString::number(heads_));
|
||||
ui->lineEditSectors->setText(QString::number(sectors_));
|
||||
recalcSize();
|
||||
}
|
||||
ui->lineEditCylinders->setEnabled(enabled);
|
||||
ui->lineEditHeads->setEnabled(enabled);
|
||||
ui->lineEditSectors->setEnabled(enabled);
|
||||
ui->lineEditSize->setEnabled(enabled);
|
||||
ui->comboBoxType->setEnabled(enabled);
|
||||
|
||||
if (index < 4) {
|
||||
ui->comboBoxBlockSize->hide();
|
||||
ui->labelBlockSize->hide();
|
||||
} else {
|
||||
ui->comboBoxBlockSize->show();
|
||||
ui->labelBlockSize->show();
|
||||
}
|
||||
}
|
||||
|
||||
/* If the disk geometry requested in the 86Box GUI is not compatible with the internal VHD geometry,
|
||||
* we adjust it to the next-largest size that is compatible. On average, this will be a difference
|
||||
* of about 21 MB, and should only be necessary for VHDs larger than 31.5 GB, so should never be more
|
||||
* than a tenth of a percent change in size.
|
||||
*/
|
||||
static void adjust_86box_geometry_for_vhd(MVHDGeom *_86box_geometry, MVHDGeom *vhd_geometry)
|
||||
{
|
||||
if (_86box_geometry->cyl <= 65535) {
|
||||
vhd_geometry->cyl = _86box_geometry->cyl;
|
||||
vhd_geometry->heads = _86box_geometry->heads;
|
||||
vhd_geometry->spt = _86box_geometry->spt;
|
||||
return;
|
||||
}
|
||||
|
||||
int desired_sectors = _86box_geometry->cyl * _86box_geometry->heads * _86box_geometry->spt;
|
||||
if (desired_sectors > 267321600)
|
||||
desired_sectors = 267321600;
|
||||
|
||||
int remainder = desired_sectors % 85680; /* 8560 is the LCM of 1008 (63*16) and 4080 (255*16) */
|
||||
if (remainder > 0)
|
||||
desired_sectors += (85680 - remainder);
|
||||
|
||||
_86box_geometry->cyl = desired_sectors / (16 * 63);
|
||||
_86box_geometry->heads = 16;
|
||||
_86box_geometry->spt = 63;
|
||||
|
||||
vhd_geometry->cyl = desired_sectors / (16 * 255);
|
||||
vhd_geometry->heads = 16;
|
||||
vhd_geometry->spt = 255;
|
||||
}
|
||||
|
||||
static HarddiskDialog* callbackPtr = nullptr;
|
||||
static MVHDGeom create_drive_vhd_fixed(const QString& fileName, HarddiskDialog* p, uint16_t cyl, uint8_t heads, uint8_t spt) {
|
||||
MVHDGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt };
|
||||
MVHDGeom vhd_geometry;
|
||||
adjust_86box_geometry_for_vhd(&_86box_geometry, &vhd_geometry);
|
||||
|
||||
int vhd_error = 0;
|
||||
QByteArray filenameBytes = fileName.toUtf8();
|
||||
callbackPtr = p;
|
||||
MVHDMeta *vhd = mvhd_create_fixed(filenameBytes.data(), vhd_geometry, &vhd_error, [](uint32_t current_sector, uint32_t total_sectors) {
|
||||
callbackPtr->fileProgress((current_sector * 100) / total_sectors);
|
||||
});
|
||||
callbackPtr = nullptr;
|
||||
|
||||
if (vhd == NULL) {
|
||||
_86box_geometry.cyl = 0;
|
||||
_86box_geometry.heads = 0;
|
||||
_86box_geometry.spt = 0;
|
||||
} else {
|
||||
mvhd_close(vhd);
|
||||
}
|
||||
|
||||
return _86box_geometry;
|
||||
}
|
||||
|
||||
static MVHDGeom create_drive_vhd_dynamic(const QString& fileName, uint16_t cyl, uint8_t heads, uint8_t spt, int blocksize) {
|
||||
MVHDGeom _86box_geometry = { .cyl = cyl, .heads = heads, .spt = spt };
|
||||
MVHDGeom vhd_geometry;
|
||||
adjust_86box_geometry_for_vhd(&_86box_geometry, &vhd_geometry);
|
||||
int vhd_error = 0;
|
||||
QByteArray filenameBytes = fileName.toUtf8();
|
||||
MVHDCreationOptions options;
|
||||
options.block_size_in_sectors = blocksize;
|
||||
options.path = filenameBytes.data();
|
||||
options.size_in_bytes = 0;
|
||||
options.geometry = vhd_geometry;
|
||||
options.type = MVHD_TYPE_DYNAMIC;
|
||||
|
||||
MVHDMeta *vhd = mvhd_create_ex(options, &vhd_error);
|
||||
if (vhd == NULL) {
|
||||
_86box_geometry.cyl = 0;
|
||||
_86box_geometry.heads = 0;
|
||||
_86box_geometry.spt = 0;
|
||||
} else {
|
||||
mvhd_close(vhd);
|
||||
}
|
||||
|
||||
return _86box_geometry;
|
||||
}
|
||||
|
||||
static MVHDGeom create_drive_vhd_diff(const QString& fileName, const QString& parentFileName, int blocksize) {
|
||||
int vhd_error = 0;
|
||||
QByteArray filenameBytes = fileName.toUtf8();
|
||||
QByteArray parentFilenameBytes = fileName.toUtf8();
|
||||
MVHDCreationOptions options;
|
||||
options.block_size_in_sectors = blocksize;
|
||||
options.path = filenameBytes.data();
|
||||
options.parent_path = parentFilenameBytes.data();
|
||||
options.type = MVHD_TYPE_DIFF;
|
||||
|
||||
MVHDMeta *vhd = mvhd_create_ex(options, &vhd_error);
|
||||
MVHDGeom vhd_geometry;
|
||||
if (vhd == NULL) {
|
||||
vhd_geometry.cyl = 0;
|
||||
vhd_geometry.heads = 0;
|
||||
vhd_geometry.spt = 0;
|
||||
} else {
|
||||
vhd_geometry = mvhd_get_geometry(vhd);
|
||||
|
||||
if (vhd_geometry.spt > 63) {
|
||||
vhd_geometry.cyl = mvhd_calc_size_sectors(&vhd_geometry) / (16 * 63);
|
||||
vhd_geometry.heads = 16;
|
||||
vhd_geometry.spt = 63;
|
||||
}
|
||||
|
||||
mvhd_close(vhd);
|
||||
}
|
||||
|
||||
return vhd_geometry;
|
||||
}
|
||||
|
||||
void HarddiskDialog::onCreateNewFile() {
|
||||
qint64 size = ui->lineEditSize->text().toUInt() << 20U;
|
||||
if (size > 0x1FFFFFFE00ll) {
|
||||
QMessageBox::critical(this, "Disk image too large", "Disk images cannot be larger than 127 GiB");
|
||||
return;
|
||||
}
|
||||
|
||||
int img_format = ui->comboBoxFormat->currentIndex();
|
||||
uint32_t zero = 0;
|
||||
uint32_t base = 0x1000;
|
||||
uint32_t sector_size = 512;
|
||||
|
||||
auto fileName = ui->fileField->fileName();
|
||||
QString expectedSuffix;
|
||||
switch (img_format) {
|
||||
case 1:
|
||||
expectedSuffix = "hdi";
|
||||
break;
|
||||
case 2:
|
||||
expectedSuffix = "hdx";
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
expectedSuffix = "vhd";
|
||||
break;
|
||||
}
|
||||
if (! expectedSuffix.isEmpty()) {
|
||||
QFileInfo fileInfo(fileName);
|
||||
if (fileInfo.suffix().compare(expectedSuffix, Qt::CaseInsensitive) != 0) {
|
||||
fileName = QString("%1.%2").arg(fileName, expectedSuffix);
|
||||
ui->fileField->setFileName(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
QFile file(fileName);
|
||||
if (! file.open(QIODevice::WriteOnly)) {
|
||||
QMessageBox::critical(this, "Unable to write file", "Make sure the file is being saved to a writable directory");
|
||||
return;
|
||||
}
|
||||
|
||||
if (img_format == 1) { /* HDI file */
|
||||
QDataStream stream(&file);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
if (size >= 0x100000000ll) {
|
||||
QMessageBox::critical(this, "Disk image too large", "HDI disk images cannot be larger than 4 GiB");
|
||||
return;
|
||||
}
|
||||
uint32_t s = static_cast<uint32_t>(size);
|
||||
stream << zero; /* 00000000: Zero/unknown */
|
||||
stream << zero; /* 00000004: Zero/unknown */
|
||||
stream << base; /* 00000008: Offset at which data starts */
|
||||
stream << s; /* 0000000C: Full size of the data (32-bit) */
|
||||
stream << sector_size; /* 00000010: Sector size in bytes */
|
||||
stream << sectors_; /* 00000014: Sectors per cylinder */
|
||||
stream << heads_; /* 00000018: Heads per cylinder */
|
||||
stream << cylinders_; /* 0000001C: Cylinders */
|
||||
|
||||
for (int i = 0; i < 0x3f8; i++) {
|
||||
stream << zero;
|
||||
}
|
||||
} else if (img_format == 2) { /* HDX file */
|
||||
QDataStream stream(&file);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
quint64 signature = 0xD778A82044445459;
|
||||
stream << signature; /* 00000000: Signature */
|
||||
stream << size; /* 00000008: Full size of the data (64-bit) */
|
||||
stream << sector_size; /* 00000010: Sector size in bytes */
|
||||
stream << sectors_; /* 00000014: Sectors per cylinder */
|
||||
stream << heads_; /* 00000018: Heads per cylinder */
|
||||
stream << cylinders_; /* 0000001C: Cylinders */
|
||||
stream << zero; /* 00000020: [Translation] Sectors per cylinder */
|
||||
stream << zero; /* 00000004: [Translation] Heads per cylinder */
|
||||
} else if (img_format >= 3) { /* VHD file */
|
||||
file.close();
|
||||
|
||||
MVHDGeom _86box_geometry;
|
||||
int block_size = ui->comboBoxBlockSize->currentIndex() == 0 ? MVHD_BLOCK_LARGE : MVHD_BLOCK_SMALL;
|
||||
switch (img_format) {
|
||||
case 3:
|
||||
{
|
||||
QProgressDialog progress("Creating disk image", QString(), 0, 100, this);
|
||||
connect(this, &HarddiskDialog::fileProgress, &progress, &QProgressDialog::setValue);
|
||||
std::thread writer([&_86box_geometry, fileName, this] {
|
||||
_86box_geometry = create_drive_vhd_fixed(fileName, this, cylinders_, heads_, sectors_);
|
||||
});
|
||||
progress.exec();
|
||||
writer.join();
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
_86box_geometry = create_drive_vhd_dynamic(fileName, cylinders_, heads_, sectors_, block_size);
|
||||
break;
|
||||
case 5:
|
||||
QString vhdParent = QFileDialog::getOpenFileName(this, "Select the parent VHD", QString(), "VHD files (*.vhd);;All files (*.*)");
|
||||
if (vhdParent.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
_86box_geometry = create_drive_vhd_diff(fileName, vhdParent, block_size);
|
||||
break;
|
||||
}
|
||||
|
||||
if (img_format != 5) {
|
||||
QMessageBox::information(this, "Disk image created", "Remember to partition and format the newly-created drive");
|
||||
}
|
||||
|
||||
ui->lineEditCylinders->setText(QString::number(_86box_geometry.cyl));
|
||||
ui->lineEditHeads->setText(QString::number(_86box_geometry.heads));
|
||||
ui->lineEditSectors->setText(QString::number(_86box_geometry.spt));
|
||||
cylinders_ = _86box_geometry.cyl;
|
||||
heads_ = _86box_geometry.heads;
|
||||
sectors_ = _86box_geometry.spt;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// formats 0, 1 and 2
|
||||
QProgressDialog progress("Creating disk image", QString(), 0, 100, this);
|
||||
connect(this, &HarddiskDialog::fileProgress, &progress, &QProgressDialog::setValue);
|
||||
std::thread writer([size, &file, this] {
|
||||
QDataStream stream(&file);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
QByteArray buf(1048576, 0);
|
||||
uint64_t mibBlocks = size >> 20;
|
||||
uint64_t restBlock = size & 0xfffff;
|
||||
|
||||
if (restBlock) {
|
||||
stream << QByteArray::fromRawData(buf.data(), restBlock);
|
||||
}
|
||||
|
||||
if (mibBlocks) {
|
||||
for (uint64_t i = 0; i < mibBlocks; ++i) {
|
||||
stream << buf;
|
||||
emit fileProgress(static_cast<int>((i * 100) / mibBlocks));
|
||||
}
|
||||
}
|
||||
emit fileProgress(100);
|
||||
});
|
||||
|
||||
progress.exec();
|
||||
writer.join();
|
||||
QMessageBox::information(this, "Disk image created", "Remember to partition and format the newly-created drive");
|
||||
}
|
||||
|
||||
static void adjust_vhd_geometry_for_86box(MVHDGeom *vhd_geometry) {
|
||||
if (vhd_geometry->spt <= 63)
|
||||
return;
|
||||
|
||||
int desired_sectors = vhd_geometry->cyl * vhd_geometry->heads * vhd_geometry->spt;
|
||||
if (desired_sectors > 267321600)
|
||||
desired_sectors = 267321600;
|
||||
|
||||
int remainder = desired_sectors % 85680; /* 8560 is the LCM of 1008 (63*16) and 4080 (255*16) */
|
||||
if (remainder > 0)
|
||||
desired_sectors -= remainder;
|
||||
|
||||
vhd_geometry->cyl = desired_sectors / (16 * 63);
|
||||
vhd_geometry->heads = 16;
|
||||
vhd_geometry->spt = 63;
|
||||
}
|
||||
|
||||
void HarddiskDialog::recalcSelection() {
|
||||
int selection = 127;
|
||||
for (int i = 0; i < 127; i++) {
|
||||
if ((cylinders_ == hdd_table[i][0]) &&
|
||||
(heads_ == hdd_table[i][1]) &&
|
||||
(sectors_ == hdd_table[i][2]))
|
||||
selection = i;
|
||||
}
|
||||
if ((selection == 127) && (heads_ == 16) && (sectors_ == 63)) {
|
||||
selection = 128;
|
||||
}
|
||||
ui->comboBoxType->setCurrentIndex(selection);
|
||||
}
|
||||
|
||||
void HarddiskDialog::onExistingFileSelected(const QString &fileName) {
|
||||
// TODO : Over to non-existing file selected
|
||||
/*
|
||||
if (!(existing & 1)) {
|
||||
f = _wfopen(wopenfilestring, L"rb");
|
||||
if (f != NULL) {
|
||||
fclose(f);
|
||||
if (settings_msgbox_ex(MBX_QUESTION_YN, (wchar_t *) IDS_4111, (wchar_t *) IDS_4118, (wchar_t *) IDS_4120, (wchar_t *) IDS_4121, NULL) != 0) / * yes * /
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
f = _wfopen(wopenfilestring, (existing & 1) ? L"rb" : L"wb");
|
||||
if (f == NULL) {
|
||||
hdd_add_file_open_error:
|
||||
fclose(f);
|
||||
settings_msgbox_header(MBX_ERROR, (existing & 1) ? (wchar_t *) IDS_4114 : (wchar_t *) IDS_4115, (existing & 1) ? (wchar_t *) IDS_4107 : (wchar_t *) IDS_4108);
|
||||
return TRUE;
|
||||
}
|
||||
*/
|
||||
|
||||
uint64_t size = 0;
|
||||
uint32_t sector_size = 0;
|
||||
uint32_t sectors = 0;
|
||||
uint32_t heads = 0;
|
||||
uint32_t cylinders = 0;
|
||||
int vhd_error = 0;
|
||||
|
||||
QFile file(fileName);
|
||||
if (! file.open(QIODevice::ReadOnly)) {
|
||||
QMessageBox::critical(this, "Unable to read file", "Make sure the file exists and is readable");
|
||||
return;
|
||||
}
|
||||
QByteArray fileNameUtf8 = fileName.toUtf8();
|
||||
|
||||
QFileInfo fi(file);
|
||||
if (image_is_hdi(fileNameUtf8.data()) || image_is_hdx(fileNameUtf8.data(), 1)) {
|
||||
file.seek(0x10);
|
||||
QDataStream stream(&file);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
stream >> sector_size;
|
||||
if (sector_size != 512) {
|
||||
QMessageBox::critical(this, "Unsupported disk image", "HDI or HDX images with a sector size other than 512 are not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
sectors = heads = cylinders = 0;
|
||||
stream >> sectors;
|
||||
stream >> heads;
|
||||
stream >> cylinders;
|
||||
} else if (image_is_vhd(fileNameUtf8.data(), 1)) {
|
||||
MVHDMeta* vhd = mvhd_open(fileNameUtf8.data(), 0, &vhd_error);
|
||||
if (vhd == nullptr) {
|
||||
QMessageBox::critical(this, "Unable to read file", "Make sure the file exists and is readable");
|
||||
return;
|
||||
} else if (vhd_error == MVHD_ERR_TIMESTAMP) {
|
||||
QMessageBox::StandardButton btn = QMessageBox::warning(this, "Parent and child disk timestamps do not match", "This could mean that the parent image was modified after the differencing image was created.\n\nIt can also happen if the image files were moved or copied, or by a bug in the program that created this disk.\n\nDo you want to fix the timestamps?", QMessageBox::Yes | QMessageBox::No);
|
||||
if (btn == QMessageBox::Yes) {
|
||||
int ts_res = mvhd_diff_update_par_timestamp(vhd, &vhd_error);
|
||||
if (ts_res != 0) {
|
||||
QMessageBox::critical(this, "Error", "Could not fix VHD timestamp");
|
||||
mvhd_close(vhd);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
mvhd_close(vhd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MVHDGeom vhd_geom = mvhd_get_geometry(vhd);
|
||||
adjust_vhd_geometry_for_86box(&vhd_geom);
|
||||
cylinders = vhd_geom.cyl;
|
||||
heads = vhd_geom.heads;
|
||||
sectors = vhd_geom.spt;
|
||||
size = static_cast<uint64_t>(cylinders * heads * sectors * 512);
|
||||
mvhd_close(vhd);
|
||||
} else {
|
||||
size = file.size();
|
||||
if (((size % 17) == 0) && (size <= 142606336)) {
|
||||
sectors = 17;
|
||||
if (size <= 26738688)
|
||||
heads = 4;
|
||||
else if (((size % 3072) == 0) && (size <= 53477376))
|
||||
heads = 6;
|
||||
else {
|
||||
int i;
|
||||
for (i = 5; i < 16; i++) {
|
||||
if (((size % (i << 9)) == 0) && (size <= ((i * 17) << 19)))
|
||||
break;
|
||||
if (i == 5)
|
||||
i++;
|
||||
}
|
||||
heads = i;
|
||||
}
|
||||
} else {
|
||||
sectors = 63;
|
||||
heads = 16;
|
||||
}
|
||||
|
||||
cylinders = ((size >> 9) / heads) / sectors;
|
||||
}
|
||||
|
||||
if ((sectors > max_sectors) || (heads > max_heads) || (cylinders > max_cylinders)) {
|
||||
QMessageBox::critical(this, "Unable to read file", "Make sure the file exists and is readable");
|
||||
return;
|
||||
}
|
||||
|
||||
heads_ = heads;
|
||||
sectors_ = sectors;
|
||||
cylinders_ = cylinders;
|
||||
ui->lineEditCylinders->setText(QString::number(cylinders));
|
||||
ui->lineEditHeads->setText(QString::number(heads));
|
||||
ui->lineEditSectors->setText(QString::number(sectors));
|
||||
recalcSize();
|
||||
recalcSelection();
|
||||
|
||||
ui->lineEditCylinders->setEnabled(true);
|
||||
ui->lineEditHeads->setEnabled(true);
|
||||
ui->lineEditSectors->setEnabled(true);
|
||||
ui->lineEditSize->setEnabled(true);
|
||||
ui->comboBoxType->setEnabled(true);
|
||||
}
|
||||
|
||||
void HarddiskDialog::recalcSize() {
|
||||
uint64_t size = (static_cast<uint64_t>(cylinders_) * static_cast<uint64_t>(heads_) * static_cast<uint64_t>(sectors_)) << 9;
|
||||
ui->lineEditSize->setText(QString::number(size >> 20));
|
||||
}
|
||||
|
||||
bool HarddiskDialog::checkAndAdjustSectors() {
|
||||
if (sectors_ > max_sectors) {
|
||||
sectors_ = max_sectors;
|
||||
ui->lineEditSectors->setText(QString::number(max_sectors));
|
||||
recalcSize();
|
||||
recalcSelection();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HarddiskDialog::checkAndAdjustHeads() {
|
||||
if (heads_ > max_heads) {
|
||||
heads_ = max_heads;
|
||||
ui->lineEditHeads->setText(QString::number(max_heads));
|
||||
recalcSize();
|
||||
recalcSelection();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HarddiskDialog::checkAndAdjustCylinders() {
|
||||
if (cylinders_ > max_cylinders) {
|
||||
cylinders_ = max_cylinders;
|
||||
ui->lineEditCylinders->setText(QString::number(max_cylinders));
|
||||
recalcSize();
|
||||
recalcSelection();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void HarddiskDialog::on_comboBoxBus_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ui->comboBoxBus->currentData().toInt()) {
|
||||
case HDD_BUS_DISABLED:
|
||||
default:
|
||||
max_sectors = max_heads = max_cylinders = 0;
|
||||
break;
|
||||
case HDD_BUS_MFM:
|
||||
max_sectors = 26; /* 17 for MFM, 26 for RLL. */
|
||||
max_heads = 15;
|
||||
max_cylinders = 2047;
|
||||
break;
|
||||
case HDD_BUS_XTA:
|
||||
max_sectors = 63;
|
||||
max_heads = 16;
|
||||
max_cylinders = 1023;
|
||||
break;
|
||||
case HDD_BUS_ESDI:
|
||||
max_sectors = 99; /* ESDI drives usually had 32 to 43 sectors per track. */
|
||||
max_heads = 16;
|
||||
max_cylinders = 266305;
|
||||
break;
|
||||
case HDD_BUS_IDE:
|
||||
max_sectors = 63;
|
||||
max_heads = 255;
|
||||
max_cylinders = 266305;
|
||||
break;
|
||||
case HDD_BUS_ATAPI:
|
||||
case HDD_BUS_SCSI:
|
||||
max_sectors = 99;
|
||||
max_heads = 255;
|
||||
max_cylinders = 266305;
|
||||
break;
|
||||
}
|
||||
|
||||
checkAndAdjustCylinders();
|
||||
checkAndAdjustHeads();
|
||||
checkAndAdjustSectors();
|
||||
|
||||
if (ui->lineEditCylinders->validator() != nullptr) {
|
||||
delete ui->lineEditCylinders->validator();
|
||||
}
|
||||
if (ui->lineEditHeads->validator() != nullptr) {
|
||||
delete ui->lineEditHeads->validator();
|
||||
}
|
||||
if (ui->lineEditSectors->validator() != nullptr) {
|
||||
delete ui->lineEditSectors->validator();
|
||||
}
|
||||
|
||||
ui->lineEditCylinders->setValidator(new QIntValidator(1, max_cylinders, this));
|
||||
ui->lineEditHeads->setValidator(new QIntValidator(1, max_heads, this));
|
||||
ui->lineEditSectors->setValidator(new QIntValidator(1, max_sectors, this));
|
||||
|
||||
Harddrives::populateBusChannels(ui->comboBoxChannel->model(), ui->comboBoxBus->currentData().toInt());
|
||||
}
|
||||
|
||||
void HarddiskDialog::on_lineEditSize_textEdited(const QString &text) {
|
||||
uint32_t size = text.toUInt();
|
||||
/* This is needed to ensure VHD standard compliance. */
|
||||
hdd_image_calc_chs(&cylinders_, &heads_, §ors_, size);
|
||||
ui->lineEditCylinders->setText(QString::number(cylinders_));
|
||||
ui->lineEditHeads->setText(QString::number(heads_));
|
||||
ui->lineEditSectors->setText(QString::number(sectors_));
|
||||
recalcSelection();
|
||||
|
||||
checkAndAdjustCylinders();
|
||||
checkAndAdjustHeads();
|
||||
checkAndAdjustSectors();
|
||||
}
|
||||
|
||||
void HarddiskDialog::on_lineEditCylinders_textEdited(const QString &text) {
|
||||
cylinders_ = text.toUInt();
|
||||
if (checkAndAdjustCylinders()) {
|
||||
recalcSize();
|
||||
recalcSelection();
|
||||
}
|
||||
}
|
||||
|
||||
void HarddiskDialog::on_lineEditHeads_textEdited(const QString &text) {
|
||||
heads_ = text.toUInt();
|
||||
if (checkAndAdjustHeads()) {
|
||||
recalcSize();
|
||||
recalcSelection();
|
||||
}
|
||||
}
|
||||
|
||||
void HarddiskDialog::on_lineEditSectors_textEdited(const QString &text) {
|
||||
sectors_ = text.toUInt();
|
||||
if (checkAndAdjustSectors()) {
|
||||
recalcSize();
|
||||
recalcSelection();
|
||||
}
|
||||
}
|
||||
|
||||
void HarddiskDialog::on_comboBoxType_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((index != 127) && (index != 128)) {
|
||||
cylinders_ = hdd_table[index][0];
|
||||
heads_ = hdd_table[index][1];
|
||||
sectors_ = hdd_table[index][2];
|
||||
ui->lineEditCylinders->setText(QString::number(cylinders_));
|
||||
ui->lineEditHeads->setText(QString::number(heads_));
|
||||
ui->lineEditSectors->setText(QString::number(sectors_));
|
||||
recalcSize();
|
||||
} else if (index == 128) {
|
||||
heads_ = 16;
|
||||
sectors_ = 63;
|
||||
ui->lineEditHeads->setText(QString::number(heads_));
|
||||
ui->lineEditSectors->setText(QString::number(sectors_));
|
||||
recalcSize();
|
||||
}
|
||||
|
||||
checkAndAdjustCylinders();
|
||||
checkAndAdjustHeads();
|
||||
checkAndAdjustSectors();
|
||||
}
|
57
src/qt/qt_harddiskdialog.hpp
Normal file
57
src/qt/qt_harddiskdialog.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef QT_HARDDISKDIALOG_HPP
|
||||
#define QT_HARDDISKDIALOG_HPP
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class HarddiskDialog;
|
||||
}
|
||||
|
||||
class HarddiskDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit HarddiskDialog(bool existing, QWidget *parent = nullptr);
|
||||
~HarddiskDialog();
|
||||
|
||||
uint8_t bus() const;
|
||||
uint8_t channel() const;
|
||||
QString fileName() const;
|
||||
uint32_t cylinders() const { return cylinders_; }
|
||||
uint32_t heads() const { return heads_; }
|
||||
uint32_t sectors() const { return sectors_; }
|
||||
|
||||
signals:
|
||||
void fileProgress(int i);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxType_currentIndexChanged(int index);
|
||||
void on_lineEditSectors_textEdited(const QString &arg1);
|
||||
void on_lineEditHeads_textEdited(const QString &arg1);
|
||||
void on_lineEditCylinders_textEdited(const QString &arg1);
|
||||
void on_lineEditSize_textEdited(const QString &arg1);
|
||||
void on_comboBoxBus_currentIndexChanged(int index);
|
||||
void on_comboBoxFormat_currentIndexChanged(int index);
|
||||
void onCreateNewFile();
|
||||
void onExistingFileSelected(const QString& fileName);
|
||||
|
||||
private:
|
||||
Ui::HarddiskDialog *ui;
|
||||
|
||||
uint32_t cylinders_;
|
||||
uint32_t heads_;
|
||||
uint32_t sectors_;
|
||||
|
||||
uint32_t max_sectors = 0;
|
||||
uint32_t max_heads = 0;
|
||||
uint32_t max_cylinders = 0;
|
||||
|
||||
bool checkAndAdjustCylinders();
|
||||
bool checkAndAdjustHeads();
|
||||
bool checkAndAdjustSectors();
|
||||
void recalcSize();
|
||||
void recalcSelection();
|
||||
};
|
||||
|
||||
#endif // QT_HARDDISKDIALOG_HPP
|
230
src/qt/qt_harddiskdialog.ui
Normal file
230
src/qt/qt_harddiskdialog.ui
Normal file
@ -0,0 +1,230 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>HarddiskDialog</class>
|
||||
<widget class="QDialog" name="HarddiskDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>File name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="FileField" name="fileField" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Cylinders</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Sectors</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEditCylinders"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEditSize"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Size (MiB)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Heads</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLineEdit" name="lineEditHeads">
|
||||
<property name="maxLength">
|
||||
<number>32767</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<widget class="QLineEdit" name="lineEditSectors">
|
||||
<property name="maxLength">
|
||||
<number>32767</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3" colspan="3">
|
||||
<widget class="QComboBox" name="comboBoxType"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Bus</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxBus"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Channel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxChannel"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayoutFormat">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelFormat">
|
||||
<property name="text">
|
||||
<string>Format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxFormat"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelBlockSize">
|
||||
<property name="text">
|
||||
<string>Block Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxBlockSize"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>FileField</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>qt_filefield.hpp</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>lineEditCylinders</tabstop>
|
||||
<tabstop>lineEditHeads</tabstop>
|
||||
<tabstop>lineEditSectors</tabstop>
|
||||
<tabstop>lineEditSize</tabstop>
|
||||
<tabstop>comboBoxType</tabstop>
|
||||
<tabstop>comboBoxBus</tabstop>
|
||||
<tabstop>comboBoxChannel</tabstop>
|
||||
<tabstop>comboBoxFormat</tabstop>
|
||||
<tabstop>comboBoxBlockSize</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>HarddiskDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>HarddiskDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
101
src/qt/qt_harddrive_common.cpp
Normal file
101
src/qt/qt_harddrive_common.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
#include "qt_harddrive_common.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
extern "C" {
|
||||
#include <86box/hdd.h>
|
||||
}
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
void Harddrives::populateBuses(QAbstractItemModel *model) {
|
||||
model->removeRows(0, model->rowCount());
|
||||
model->insertRows(0, 6);
|
||||
model->setData(model->index(0, 0), "MFM/RLL");
|
||||
model->setData(model->index(1, 0), "XT IDE");
|
||||
model->setData(model->index(2, 0), "ESDI");
|
||||
model->setData(model->index(3, 0), "IDE");
|
||||
model->setData(model->index(4, 0), "ATAPI");
|
||||
model->setData(model->index(5, 0), "SCSI");
|
||||
|
||||
model->setData(model->index(0, 0), HDD_BUS_MFM, Qt::UserRole);
|
||||
model->setData(model->index(1, 0), HDD_BUS_XTA, Qt::UserRole);
|
||||
model->setData(model->index(2, 0), HDD_BUS_ESDI, Qt::UserRole);
|
||||
model->setData(model->index(3, 0), HDD_BUS_IDE, Qt::UserRole);
|
||||
model->setData(model->index(4, 0), HDD_BUS_ATAPI, Qt::UserRole);
|
||||
model->setData(model->index(5, 0), HDD_BUS_SCSI, Qt::UserRole);
|
||||
}
|
||||
|
||||
void Harddrives::populateRemovableBuses(QAbstractItemModel *model) {
|
||||
model->removeRows(0, model->rowCount());
|
||||
model->insertRows(0, 3);
|
||||
model->setData(model->index(0, 0), "Disabled");
|
||||
model->setData(model->index(1, 0), "ATAPI");
|
||||
model->setData(model->index(2, 0), "SCSI");
|
||||
|
||||
model->setData(model->index(0, 0), HDD_BUS_DISABLED, Qt::UserRole);
|
||||
model->setData(model->index(1, 0), HDD_BUS_ATAPI, Qt::UserRole);
|
||||
model->setData(model->index(2, 0), HDD_BUS_SCSI, Qt::UserRole);
|
||||
}
|
||||
|
||||
void Harddrives::populateBusChannels(QAbstractItemModel *model, int bus) {
|
||||
model->removeRows(0, model->rowCount());
|
||||
|
||||
int busRows = 0;
|
||||
int shifter = 1;
|
||||
int orer = 1;
|
||||
int subChannelWidth = 1;
|
||||
switch (bus) {
|
||||
case HDD_BUS_MFM:
|
||||
case HDD_BUS_XTA:
|
||||
case HDD_BUS_ESDI:
|
||||
busRows = 2;
|
||||
break;
|
||||
case HDD_BUS_IDE:
|
||||
case HDD_BUS_ATAPI:
|
||||
busRows = 8;
|
||||
break;
|
||||
case HDD_BUS_SCSI:
|
||||
shifter = 4;
|
||||
orer = 15;
|
||||
busRows = 64;
|
||||
subChannelWidth = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
model->insertRows(0, busRows);
|
||||
for (int i = 0; i < busRows; ++i) {
|
||||
auto idx = model->index(i, 0);
|
||||
model->setData(idx, QString("%1:%2").arg(i >> shifter).arg(i & orer, subChannelWidth, 10, QChar('0')));
|
||||
model->setData(idx, ((i >> shifter) << shifter) | (i & orer), Qt::UserRole);
|
||||
}
|
||||
}
|
||||
|
||||
QString Harddrives::BusChannelName(uint8_t bus, uint8_t channel) {
|
||||
QString busName;
|
||||
switch(bus) {
|
||||
case HDD_BUS_DISABLED:
|
||||
busName = QString("Disabled");
|
||||
break;
|
||||
case HDD_BUS_MFM:
|
||||
busName = QString("MFM/RLL (%1:%2)").arg(channel >> 1).arg(channel & 1);
|
||||
break;
|
||||
case HDD_BUS_XTA:
|
||||
busName = QString("XT IDE (%1:%2)").arg(channel >> 1).arg(channel & 1);
|
||||
break;
|
||||
case HDD_BUS_ESDI:
|
||||
busName = QString("ESDI (%1:%2)").arg(channel >> 1).arg(channel & 1);
|
||||
break;
|
||||
case HDD_BUS_IDE:
|
||||
busName = QString("IDE (%1:%2)").arg(channel >> 1).arg(channel & 1);
|
||||
break;
|
||||
case HDD_BUS_ATAPI:
|
||||
busName = QString("ATAPI (%1:%2)").arg(channel >> 1).arg(channel & 1);
|
||||
break;
|
||||
case HDD_BUS_SCSI:
|
||||
busName = QString("SCSI (%1:%2)").arg(channel >> 4).arg(channel & 15, 2, 10, QChar('0'));
|
||||
break;
|
||||
}
|
||||
|
||||
return busName;
|
||||
}
|
13
src/qt/qt_harddrive_common.hpp
Normal file
13
src/qt/qt_harddrive_common.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class QString;
|
||||
class QAbstractItemModel;
|
||||
|
||||
namespace Harddrives {
|
||||
void populateBuses(QAbstractItemModel* model);
|
||||
void populateRemovableBuses(QAbstractItemModel* model);
|
||||
void populateBusChannels(QAbstractItemModel* model, int bus);
|
||||
QString BusChannelName(uint8_t bus, uint8_t channel);
|
||||
};
|
104
src/qt/qt_main.cpp
Normal file
104
src/qt/qt_main.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QElapsedTimer>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
#include <86box/86box.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/ui.h>
|
||||
#include <86box/video.h>
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "qt_mainwindow.hpp"
|
||||
#include "qt_sdl.h"
|
||||
|
||||
|
||||
// Void Cast
|
||||
#define VC(x) const_cast<wchar_t*>(x)
|
||||
|
||||
extern QElapsedTimer elapsed_timer;
|
||||
extern int nvr_dosave;
|
||||
extern MainWindow* main_window;
|
||||
|
||||
extern "C" {
|
||||
extern int qt_nvr_save(void);
|
||||
}
|
||||
|
||||
void
|
||||
main_thread_fn()
|
||||
{
|
||||
uint64_t old_time, new_time;
|
||||
int drawits, frames;
|
||||
|
||||
QThread::currentThread()->setPriority(QThread::HighestPriority);
|
||||
framecountx = 0;
|
||||
//title_update = 1;
|
||||
old_time = elapsed_timer.elapsed();
|
||||
drawits = frames = 0;
|
||||
while (!is_quit && cpu_thread_run) {
|
||||
/* See if it is time to run a frame of code. */
|
||||
new_time = elapsed_timer.elapsed();
|
||||
drawits += (new_time - old_time);
|
||||
old_time = new_time;
|
||||
if (drawits > 0 && !dopause) {
|
||||
/* Yes, so do one frame now. */
|
||||
drawits -= 10;
|
||||
if (drawits > 50)
|
||||
drawits = 0;
|
||||
|
||||
/* Run a block of code. */
|
||||
pc_run();
|
||||
|
||||
/* Every 200 frames we save the machine status. */
|
||||
if (++frames >= 200 && nvr_dosave) {
|
||||
qt_nvr_save();
|
||||
nvr_dosave = 0;
|
||||
frames = 0;
|
||||
}
|
||||
} else /* Just so we dont overload the host OS. */
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
|
||||
/* If needed, handle a screen resize. */
|
||||
if (doresize && !video_fullscreen && !is_quit) {
|
||||
if (vid_resize & 2)
|
||||
plat_resize(fixed_size_x, fixed_size_y);
|
||||
else
|
||||
plat_resize(scrnsz_x, scrnsz_y);
|
||||
doresize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
is_quit = 1;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
QApplication app(argc, argv);
|
||||
elapsed_timer.start();
|
||||
|
||||
pc_init(argc, argv);
|
||||
if (! pc_init_modules()) {
|
||||
ui_msgbox_header(MBX_FATAL, VC(L"No ROMs found."), VC(L"86Box could not find any usable ROM images.\n\nPlease download a ROM set and extract it into the \"roms\" directory."));
|
||||
return 6;
|
||||
}
|
||||
|
||||
main_window = new MainWindow();
|
||||
main_window->show();
|
||||
|
||||
pc_reset_hard_init();
|
||||
|
||||
/* Set the PAUSE mode depending on the renderer. */
|
||||
// plat_pause(0);
|
||||
|
||||
/* Initialize the rendering window, or fullscreen. */
|
||||
auto main_thread = std::thread([] {
|
||||
main_thread_fn();
|
||||
});
|
||||
|
||||
auto ret = app.exec();
|
||||
cpu_thread_run = 0;
|
||||
main_thread.join();
|
||||
|
||||
return ret;
|
||||
}
|
299
src/qt/qt_mainwindow.cpp
Normal file
299
src/qt/qt_mainwindow.cpp
Normal file
@ -0,0 +1,299 @@
|
||||
#include "qt_mainwindow.hpp"
|
||||
#include "ui_qt_mainwindow.h"
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/mouse.h>
|
||||
#include <86box/config.h>
|
||||
#include <86box/plat.h>
|
||||
|
||||
#include "qt_sdl.h"
|
||||
};
|
||||
|
||||
#include <QWindow>
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "qt_settings.hpp"
|
||||
|
||||
CentralWidget::CentralWidget(QWidget *parent) : QWidget(parent) {}
|
||||
CentralWidget::~CentralWidget() = default;
|
||||
|
||||
MainWindowLabel::MainWindowLabel(QWidget *parent) : QLabel(parent) {
|
||||
setMouseTracking(true);
|
||||
}
|
||||
MainWindowLabel::~MainWindowLabel() = default;
|
||||
void MainWindowLabel::mouseMoveEvent(QMouseEvent *event) {
|
||||
pos_ = event->pos();
|
||||
}
|
||||
void MainWindowLabel::mousePressEvent(QMouseEvent *event) {
|
||||
buttons_ = event->buttons();
|
||||
}
|
||||
void MainWindowLabel::mouseReleaseEvent(QMouseEvent *event) {
|
||||
buttons_ = event->buttons();
|
||||
}
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow)
|
||||
{
|
||||
Q_INIT_RESOURCE(qt_resources);
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(this, &MainWindow::pollMouse, this, [] {
|
||||
sdl_mouse_poll();
|
||||
});
|
||||
|
||||
connect(this, &MainWindow::setMouseCapture, this, [](bool state) {
|
||||
mouse_capture = state ? 1 : 0;
|
||||
sdl_mouse_capture(mouse_capture);
|
||||
});
|
||||
|
||||
connect(this, &MainWindow::setFullscreen, this, [](bool state) {
|
||||
video_fullscreen = state ? 1 : 0;
|
||||
sdl_set_fs(video_fullscreen);
|
||||
});
|
||||
|
||||
connect(this, &MainWindow::resizeContents, this, [this](int w, int h) {
|
||||
sdl_resize(w, h);
|
||||
});
|
||||
|
||||
connect(ui->menubar, &QMenuBar::triggered, this, [] {
|
||||
config_save();
|
||||
});
|
||||
|
||||
ui->actionKeyboard_requires_capture->setChecked(kbd_req_capture);
|
||||
ui->actionRight_CTRL_is_left_ALT->setChecked(rctrl_is_lalt);
|
||||
|
||||
sdl_inits();
|
||||
sdl_timer = new QTimer(this);
|
||||
connect(sdl_timer, &QTimer::timeout, this, [] {
|
||||
auto status = sdl_main();
|
||||
if (status == SdlMainQuit) {
|
||||
QApplication::quit();
|
||||
}
|
||||
});
|
||||
sdl_timer->start(5);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
sdl_close();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::on_actionKeyboard_requires_capture_triggered() {
|
||||
kbd_req_capture ^= 1;
|
||||
}
|
||||
|
||||
void MainWindow::on_actionRight_CTRL_is_left_ALT_triggered() {
|
||||
rctrl_is_lalt ^= 1;
|
||||
}
|
||||
|
||||
void MainWindow::on_actionHard_Reset_triggered() {
|
||||
pc_reset_hard();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionCtrl_Alt_Del_triggered() {
|
||||
pc_send_cad();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionCtrl_Alt_Esc_triggered() {
|
||||
pc_send_cae();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionPause_triggered() {
|
||||
plat_pause(dopause ^ 1);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionExit_triggered() {
|
||||
close();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSettings_triggered() {
|
||||
Settings settings;
|
||||
settings.exec();
|
||||
|
||||
switch (settings.result()) {
|
||||
case QDialog::Accepted:
|
||||
/*
|
||||
pc_reset_hard_close();
|
||||
settings.save();
|
||||
config_changed = 2;
|
||||
pc_reset_hard_init();
|
||||
*/
|
||||
settings.save();
|
||||
config_changed = 2;
|
||||
pc_reset_hard();
|
||||
|
||||
break;
|
||||
case QDialog::Rejected:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const int keycode_entries = 136;
|
||||
// xmodmap -pk
|
||||
static const uint16_t xfree86_keycode_table[keycode_entries] = {
|
||||
/* 0 */ 0,
|
||||
/* 1 */ 0,
|
||||
/* 2 */ 0,
|
||||
/* 3 */ 0,
|
||||
/* 4 */ 0,
|
||||
/* 5 */ 0,
|
||||
/* 6 */ 0,
|
||||
/* 7 */ 0,
|
||||
/* 8 */ 0,
|
||||
/* 9 */ 0x01, // Esc
|
||||
/* 10 */ 0x02, // 1
|
||||
/* 11 */ 0x03, // 2
|
||||
/* 12 */ 0x04, // 3
|
||||
/* 13 */ 0x05, // 4
|
||||
/* 14 */ 0x06, // 5
|
||||
/* 15 */ 0x07, // 6
|
||||
/* 16 */ 0x08, // 7
|
||||
/* 17 */ 0x09, // 8
|
||||
/* 18 */ 0x0a, // 9
|
||||
/* 19 */ 0x0b, // 0
|
||||
/* 20 */ 0x0c, // -
|
||||
/* 21 */ 0x0d, // =
|
||||
/* 22 */ 0x0e, // BackSpace
|
||||
/* 23 */ 0x0f, // Tab
|
||||
/* 24 */ 0x10, // Q
|
||||
/* 25 */ 0x11, // W
|
||||
/* 26 */ 0x12, // E
|
||||
/* 27 */ 0x13, // R
|
||||
/* 28 */ 0x14, // T
|
||||
/* 29 */ 0x15, // Y
|
||||
/* 30 */ 0x16, // U
|
||||
/* 31 */ 0x17, // I
|
||||
/* 32 */ 0x18, // O
|
||||
/* 33 */ 0x19, // P
|
||||
/* 34 */ 0x1a, // [
|
||||
/* 35 */ 0x1b, // ]
|
||||
/* 36 */ 0x1c, // Return
|
||||
/* 37 */ 0x1d, // LeftControl
|
||||
/* 38 */ 0x1e, // A
|
||||
/* 39 */ 0x1f, // S
|
||||
/* 40 */ 0x20, // D
|
||||
/* 41 */ 0x21, // F
|
||||
/* 42 */ 0x22, // G
|
||||
/* 43 */ 0x23, // H
|
||||
/* 44 */ 0x24, // J
|
||||
/* 45 */ 0x25, // K
|
||||
/* 46 */ 0x26, // L
|
||||
/* 47 */ 0x27, // ;
|
||||
/* 48 */ 0x28, // '
|
||||
/* 49 */ 0x29, // ` (???)
|
||||
/* 50 */ 0x2a, // LeftShift
|
||||
/* 51 */ 0x2b, // BackSlash
|
||||
/* 52 */ 0x2c, // Z
|
||||
/* 53 */ 0x2d, // X
|
||||
/* 54 */ 0x2e, // C
|
||||
/* 55 */ 0x2f, // V
|
||||
/* 56 */ 0x30, // B
|
||||
/* 57 */ 0x31, // N
|
||||
/* 58 */ 0x32, // M
|
||||
/* 59 */ 0x33, // ,
|
||||
/* 60 */ 0x34, // .
|
||||
/* 61 */ 0x35, // -
|
||||
/* 62 */ 0x36, // RightShift
|
||||
/* 63 */ 0x37, // KeyPad Multiply
|
||||
/* 64 */ 0x38, // LeftAlt
|
||||
/* 65 */ 0x39, // Space
|
||||
/* 66 */ 0x3a, // CapsLock
|
||||
/* 67 */ 0x3b, // F01
|
||||
/* 68 */ 0x3c, // F02
|
||||
/* 69 */ 0x3d, // F03
|
||||
/* 70 */ 0x3e, // F04
|
||||
/* 71 */ 0x3f, // F05
|
||||
/* 72 */ 0x40, // F06
|
||||
/* 73 */ 0x41, // F07
|
||||
/* 74 */ 0x42, // F08
|
||||
/* 75 */ 0x43, // F09
|
||||
/* 76 */ 0x44, // F10
|
||||
/* 77 */ 0x45, // NumLock
|
||||
/* 78 */ 0x46, // ScrollLock
|
||||
/* 79 */ 0x47, // KeyPad7
|
||||
/* 80 */ 0x48, // KeyPad8
|
||||
/* 81 */ 0x49, // KeyPad9
|
||||
/* 82 */ 0x4a, // KeyPad Minus
|
||||
/* 83 */ 0x4b, // KeyPad4
|
||||
/* 84 */ 0x4c, // KeyPad5
|
||||
/* 85 */ 0x4d, // KeyPad6
|
||||
/* 86 */ 0x4e, // KeyPad Plus
|
||||
/* 87 */ 0x4f, // KeyPad1
|
||||
/* 88 */ 0x50, // KeyPad2
|
||||
/* 89 */ 0x51, // KeyPad3
|
||||
/* 90 */ 0x52, // KeyPad0
|
||||
/* 91 */ 0x53, // KeyPad .
|
||||
/* 92 */ 0,
|
||||
/* 93 */ 0,
|
||||
/* 94 */ 0x56, // Less/Great
|
||||
/* 95 */ 0x57, // F11
|
||||
/* 96 */ 0x58, // F12
|
||||
/* 97 */ 0,
|
||||
/* 98 */ 0,
|
||||
/* 99 */ 0,
|
||||
/* 100 */ 0,
|
||||
/* 101 */ 0,
|
||||
/* 102 */ 0,
|
||||
/* 103 */ 0,
|
||||
/* 104 */ 0x11c, // KeyPad Enter
|
||||
/* 105 */ 0x11d, // RightControl
|
||||
/* 106 */ 0x135, // KeyPad Divide
|
||||
/* 107 */ 0x137, // PrintScreen / SysReq
|
||||
/* 108 */ 0x138, // RightAlt
|
||||
/* 109 */ 0,
|
||||
/* 110 */ 0x147, // Home
|
||||
/* 111 */ 0x148, // Up
|
||||
/* 112 */ 0x149, // PageUp
|
||||
/* 113 */ 0x14b, // Left
|
||||
/* 114 */ 0x14d, // Right
|
||||
/* 115 */ 0x14f, // End
|
||||
/* 116 */ 0x150, // Down
|
||||
/* 117 */ 0x151, // PageDown
|
||||
/* 118 */ 0x152, // Insert
|
||||
/* 119 */ 0x153, // Delete
|
||||
/* 120 */ 0,
|
||||
/* 121 */ 0,
|
||||
/* 122 */ 0,
|
||||
/* 123 */ 0,
|
||||
/* 124 */ 0,
|
||||
/* 125 */ 0,
|
||||
/* 126 */ 0,
|
||||
/* 127 */ 0,
|
||||
/* 128 */ 0,
|
||||
/* 129 */ 0,
|
||||
/* 130 */ 0,
|
||||
/* 131 */ 0,
|
||||
/* 132 */ 0,
|
||||
/* 133 */ 0x15b, // SuperLeft
|
||||
/* 134 */ 0x15c, // SuperRight
|
||||
/* 135 */ 0x15d, // Application
|
||||
};
|
||||
|
||||
static void handle_keypress_event(int state, quint32 native_scancode) {
|
||||
if (native_scancode > keycode_entries) {
|
||||
return;
|
||||
}
|
||||
uint16_t translated_code = xfree86_keycode_table[native_scancode];
|
||||
if (translated_code == 0) {
|
||||
return;
|
||||
}
|
||||
keyboard_input(state, translated_code);
|
||||
|
||||
if (keyboard_isfsexit() > 0) {
|
||||
plat_setfullscreen(0);
|
||||
}
|
||||
|
||||
if (keyboard_ismsexit() > 0) {
|
||||
plat_mouse_capture(0);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionFullscreen_triggered() {
|
||||
setFullscreen(true);
|
||||
}
|
83
src/qt/qt_mainwindow.hpp
Normal file
83
src/qt/qt_mainwindow.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
#ifndef QT_MAINWINDOW_HPP
|
||||
#define QT_MAINWINDOW_HPP
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QLabel>
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindowLabel : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MainWindowLabel(QWidget *parent = nullptr);
|
||||
~MainWindowLabel();
|
||||
|
||||
const QPoint& pos() { return pos_; }
|
||||
Qt::MouseButtons buttons() { return buttons_; }
|
||||
protected:
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
private:
|
||||
QPoint pos_;
|
||||
Qt::MouseButtons buttons_;
|
||||
};
|
||||
|
||||
class CentralWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CentralWidget(QWidget *parent = nullptr);
|
||||
~CentralWidget();
|
||||
|
||||
void setSizeHint(QSize size) { size_ = size; }
|
||||
QSize sizeHint() const override { return size_; }
|
||||
private:
|
||||
QSize size_;
|
||||
};
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
signals:
|
||||
void paint(const QImage& image);
|
||||
void resizeContents(int w, int h);
|
||||
void pollMouse();
|
||||
|
||||
void setFullscreen(bool state);
|
||||
void setMouseCapture(bool state);
|
||||
|
||||
private slots:
|
||||
void on_actionFullscreen_triggered();
|
||||
|
||||
private slots:
|
||||
void on_actionSettings_triggered();
|
||||
void on_actionExit_triggered();
|
||||
void on_actionPause_triggered();
|
||||
void on_actionCtrl_Alt_Del_triggered();
|
||||
void on_actionCtrl_Alt_Esc_triggered();
|
||||
void on_actionHard_Reset_triggered();
|
||||
void on_actionRight_CTRL_is_left_ALT_triggered();
|
||||
void on_actionKeyboard_requires_capture_triggered();
|
||||
|
||||
private:
|
||||
struct DeltaPos {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int z = 0;
|
||||
};
|
||||
Ui::MainWindow *ui;
|
||||
DeltaPos mouseDelta;
|
||||
QWindow* sdl_wrapped_window;
|
||||
QWidget* sdl_wrapped_widget;
|
||||
QTimer* sdl_timer;
|
||||
};
|
||||
|
||||
#endif // QT_MAINWINDOW_HPP
|
143
src/qt/qt_mainwindow.ui
Normal file
143
src/qt/qt_mainwindow.ui
Normal file
@ -0,0 +1,143 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>724</width>
|
||||
<height>274</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>86Box</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>724</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuAction">
|
||||
<property name="title">
|
||||
<string>Action</string>
|
||||
</property>
|
||||
<addaction name="actionKeyboard_requires_capture"/>
|
||||
<addaction name="actionRight_CTRL_is_left_ALT"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionHard_Reset"/>
|
||||
<addaction name="actionCtrl_Alt_Del"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionCtrl_Alt_Esc"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionPause"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionExit"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuTools">
|
||||
<property name="title">
|
||||
<string>Tools</string>
|
||||
</property>
|
||||
<addaction name="actionSettings"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuView">
|
||||
<property name="title">
|
||||
<string>View</string>
|
||||
</property>
|
||||
<addaction name="actionFullscreen"/>
|
||||
</widget>
|
||||
<addaction name="menuAction"/>
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuTools"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<action name="actionKeyboard_requires_capture">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Keyboard requires capture</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRight_CTRL_is_left_ALT">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Right CTRL is left ALT</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHard_Reset">
|
||||
<property name="text">
|
||||
<string>Hard Reset</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCtrl_Alt_Del">
|
||||
<property name="text">
|
||||
<string>Ctrl+Alt+Del</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCtrl_Alt_Esc">
|
||||
<property name="text">
|
||||
<string>Ctrl+Alt+Esc</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPause">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Pause</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExit">
|
||||
<property name="text">
|
||||
<string>Exit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSettings">
|
||||
<property name="text">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFullscreen">
|
||||
<property name="text">
|
||||
<string>Fullscreen</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Alt+PgUp</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
32
src/qt/qt_midi.cpp
Normal file
32
src/qt/qt_midi.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include <cstdint>
|
||||
|
||||
extern "C" {
|
||||
|
||||
void plat_midi_play_msg(uint8_t *msg)
|
||||
{}
|
||||
|
||||
void plat_midi_play_sysex(uint8_t *sysex, unsigned int len)
|
||||
{}
|
||||
|
||||
void plat_midi_input_init(void)
|
||||
{}
|
||||
|
||||
void plat_midi_input_close(void)
|
||||
{}
|
||||
|
||||
int plat_midi_write(uint8_t val)
|
||||
{ return 0; }
|
||||
|
||||
void plat_midi_init()
|
||||
{}
|
||||
|
||||
void plat_midi_close()
|
||||
{}
|
||||
|
||||
int plat_midi_get_num_devs()
|
||||
{ return 0; }
|
||||
|
||||
int plat_midi_in_get_num_devs(void)
|
||||
{ return 0; }
|
||||
|
||||
}
|
15
src/qt/qt_models_common.cpp
Normal file
15
src/qt/qt_models_common.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "qt_models_common.hpp"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
int Models::AddEntry(QAbstractItemModel *model, const QString& displayRole, int userRole)
|
||||
{
|
||||
int row = model->rowCount();
|
||||
model->insertRow(row);
|
||||
auto idx = model->index(row, 0);
|
||||
|
||||
model->setData(idx, displayRole, Qt::DisplayRole);
|
||||
model->setData(idx, userRole, Qt::UserRole);
|
||||
|
||||
return row;
|
||||
}
|
8
src/qt/qt_models_common.hpp
Normal file
8
src/qt/qt_models_common.hpp
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
class QString;
|
||||
class QAbstractItemModel;
|
||||
namespace Models
|
||||
{
|
||||
int AddEntry(QAbstractItemModel* model, const QString& displayRole, int userRole);
|
||||
};
|
382
src/qt/qt_platform.cpp
Normal file
382
src/qt/qt_platform.cpp
Normal file
@ -0,0 +1,382 @@
|
||||
#include <cstdio>
|
||||
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QTemporaryFile>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include <QLibrary>
|
||||
#include <QElapsedTimer>
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
// static QByteArray buf;
|
||||
extern QElapsedTimer elapsed_timer;
|
||||
QElapsedTimer elapsed_timer;
|
||||
static std::mutex blitmx;
|
||||
|
||||
class CharPointer {
|
||||
public:
|
||||
CharPointer(char* buf, int size) : b(buf), s(size) {}
|
||||
CharPointer& operator=(const QByteArray &ba) {
|
||||
if (s > 0) {
|
||||
strncpy(b, ba.data(), s-1);
|
||||
b[s] = 0;
|
||||
} else {
|
||||
// if we haven't been told the length of b, just assume enough
|
||||
// because we didn't get it from emulator code
|
||||
strcpy(b, ba.data());
|
||||
b[ba.size()] = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
char* b;
|
||||
int s;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/gameport.h>
|
||||
#include <86box/plat_dynld.h>
|
||||
#include <86box/config.h>
|
||||
#include <86box/ui.h>
|
||||
|
||||
#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 = 0;
|
||||
int kbd_req_capture = 0;
|
||||
int hide_status_bar = 0;
|
||||
uint32_t lang_id = 0x0409, lang_sys = 0x0409; // Multilangual UI variables, for now all set to LCID of en-US
|
||||
|
||||
plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS];
|
||||
joystick_t joystick_state[MAX_JOYSTICKS];
|
||||
|
||||
int stricmp(const char* s1, const char* s2)
|
||||
{
|
||||
return QByteArray(s1).compare(s2, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
int strnicmp(const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
QByteArray b1(s1, std::min(strlen(s1), n));
|
||||
QByteArray b2(s2, std::min(strlen(s2), n));
|
||||
return b1.compare(b2, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
void
|
||||
do_stop(void)
|
||||
{
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
|
||||
void plat_get_exe_name(char *s, int size)
|
||||
{
|
||||
CharPointer(s, size) = QCoreApplication::applicationFilePath().toUtf8();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
plat_get_ticks(void)
|
||||
{
|
||||
return elapsed_timer.elapsed();
|
||||
}
|
||||
|
||||
uint64_t
|
||||
plat_timer_read(void)
|
||||
{
|
||||
return elapsed_timer.elapsed();
|
||||
}
|
||||
|
||||
FILE *
|
||||
plat_fopen(const char *path, const char *mode)
|
||||
{
|
||||
/*
|
||||
QString filepath(path);
|
||||
if (filepath.isEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
qWarning() << "plat_fopen" << filepath;
|
||||
bool ok = false;
|
||||
QFile file(filepath);
|
||||
auto mode_len = strlen(mode);
|
||||
for (size_t i = 0; i < mode_len; ++i) {
|
||||
switch (mode[i]) {
|
||||
case 'r':
|
||||
ok = file.open(QIODevice::ReadOnly);
|
||||
break;
|
||||
case 'w':
|
||||
ok = file.open(QIODevice::ReadWrite);
|
||||
break;
|
||||
case 'b':
|
||||
case 't':
|
||||
break;
|
||||
default:
|
||||
qWarning() << "Unhandled open mode" << mode[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
qDebug() << "filehandle" << file.handle();
|
||||
QFile returned;
|
||||
qDebug() << "\t" << returned.open(file.handle(), file.openMode(), QFileDevice::FileHandleFlag::DontCloseHandle);
|
||||
return fdopen(returned.handle(), mode);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
*/
|
||||
#ifdef Q_OS_WINDOWS
|
||||
wchar_t *pathw, *modew;
|
||||
int len;
|
||||
FILE *fp;
|
||||
|
||||
if (acp_utf8)
|
||||
return fopen(path, mode);
|
||||
else {
|
||||
len = mbstoc16s(NULL, path, 0) + 1;
|
||||
pathw = malloc(sizeof(wchar_t) * len);
|
||||
mbstoc16s(pathw, path, len);
|
||||
|
||||
len = mbstoc16s(NULL, mode, 0) + 1;
|
||||
modew = malloc(sizeof(wchar_t) * len);
|
||||
mbstoc16s(modew, mode, len);
|
||||
|
||||
fp = _wfopen(pathw, modew);
|
||||
|
||||
free(pathw);
|
||||
free(modew);
|
||||
|
||||
return fp;
|
||||
}
|
||||
#endif
|
||||
#ifdef Q_OS_UNIX
|
||||
return fopen(path, mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
FILE *
|
||||
plat_fopen64(const char *path, const char *mode)
|
||||
{
|
||||
return fopen(path, mode);
|
||||
}
|
||||
|
||||
int
|
||||
plat_dir_create(char *path)
|
||||
{
|
||||
return QDir().mkdir(path) ? 0 : -1;
|
||||
}
|
||||
|
||||
int
|
||||
plat_dir_check(char *path)
|
||||
{
|
||||
QFileInfo fi(path);
|
||||
return fi.isDir() ? 1 : 0;
|
||||
}
|
||||
|
||||
int
|
||||
plat_getcwd(char *bufp, int max)
|
||||
{
|
||||
CharPointer(bufp, max) = QDir::currentPath().toUtf8();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
plat_get_dirname(char *dest, const char *path)
|
||||
{
|
||||
QFileInfo fi(path);
|
||||
CharPointer(dest, -1) = fi.dir().path().toUtf8();
|
||||
}
|
||||
|
||||
char *
|
||||
plat_get_extension(char *s)
|
||||
{
|
||||
auto len = strlen(s);
|
||||
auto idx = QByteArray::fromRawData(s, len).lastIndexOf('.');
|
||||
if (idx >= 0) {
|
||||
return s+idx+1;
|
||||
}
|
||||
return s+len;
|
||||
}
|
||||
|
||||
char *
|
||||
plat_get_filename(char *s)
|
||||
{
|
||||
auto idx = QByteArray::fromRawData(s, strlen(s)).lastIndexOf(QDir::separator().toLatin1());
|
||||
if (idx >= 0) {
|
||||
return s+idx+1;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
plat_path_abs(char *path)
|
||||
{
|
||||
QFileInfo fi(path);
|
||||
return fi.isAbsolute() ? 1 : 0;
|
||||
}
|
||||
|
||||
void
|
||||
plat_path_slash(char *path)
|
||||
{
|
||||
auto len = strlen(path);
|
||||
auto separator = QDir::separator().toLatin1();
|
||||
if (path[len-1] != separator) {
|
||||
path[len] = separator;
|
||||
path[len+1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
plat_append_filename(char *dest, const char *s1, const char *s2)
|
||||
{
|
||||
strcpy(dest, s1);
|
||||
plat_path_slash(dest);
|
||||
strcat(dest, s2);
|
||||
}
|
||||
|
||||
void
|
||||
plat_tempfile(char *bufp, char *prefix, char *suffix)
|
||||
{
|
||||
QString name;
|
||||
|
||||
if (prefix != nullptr) {
|
||||
name.append(QString("%1-").arg(prefix));
|
||||
}
|
||||
|
||||
name.append("XXXXXX");
|
||||
|
||||
if (suffix != nullptr) {
|
||||
name.append(suffix);
|
||||
}
|
||||
QTemporaryFile temp(name);
|
||||
QByteArray buf(bufp);
|
||||
buf = temp.fileName().toUtf8();
|
||||
}
|
||||
|
||||
void plat_remove(char* path)
|
||||
{
|
||||
QFile(path).remove();
|
||||
}
|
||||
|
||||
void *
|
||||
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
|
||||
void *ret = mmap(0, size, PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0), MAP_ANON | MAP_PRIVATE | (executable ? MAP_JIT : 0), 0, 0);
|
||||
#else
|
||||
void *ret = mmap(0, size, PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0), MAP_ANON | MAP_PRIVATE, 0, 0);
|
||||
auto retval = *reinterpret_cast<int*>(ret);
|
||||
return (retval < 0) ? nullptr : ret;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
plat_munmap(void *ptr, size_t size)
|
||||
{
|
||||
munmap(ptr, size);
|
||||
}
|
||||
|
||||
void
|
||||
plat_pause(int p)
|
||||
{
|
||||
static wchar_t oldtitle[512];
|
||||
wchar_t title[512];
|
||||
|
||||
dopause = p;
|
||||
if (p) {
|
||||
wcsncpy(oldtitle, ui_window_title(NULL), sizeof_w(oldtitle) - 1);
|
||||
wcscpy(title, oldtitle);
|
||||
wcscat(title, L" - PAUSED -");
|
||||
ui_window_title(title);
|
||||
} else {
|
||||
ui_window_title(oldtitle);
|
||||
}
|
||||
}
|
||||
|
||||
// because we can't include nvr.h because it's got fields named new
|
||||
extern int nvr_save(void);
|
||||
|
||||
void
|
||||
plat_power_off(void)
|
||||
{
|
||||
confirm_exit = 0;
|
||||
nvr_save();
|
||||
config_save();
|
||||
|
||||
/* Deduct a sufficiently large number of cycles that no instructions will
|
||||
run before the main thread is terminated */
|
||||
cycles -= 99999999;
|
||||
|
||||
cpu_thread_run = 0;
|
||||
}
|
||||
|
||||
void set_language(uint32_t id) {
|
||||
lang_id = id;
|
||||
}
|
||||
|
||||
/* Sets up the program language before initialization. */
|
||||
uint32_t plat_language_code(char* langcode) {
|
||||
/* or maybe not */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Converts back the language code to LCID */
|
||||
void plat_language_code_r(uint32_t lcid, char* outbuf, int len) {
|
||||
/* or maybe not */
|
||||
return;
|
||||
}
|
||||
|
||||
void* dynld_module(const char *name, dllimp_t *table)
|
||||
{
|
||||
auto lib = std::unique_ptr<QLibrary>(new QLibrary(name));
|
||||
if (lib->load()) {
|
||||
for (auto imp = table; imp->name != nullptr; imp++)
|
||||
{
|
||||
if ((imp->func = reinterpret_cast<void*>(lib->resolve(imp->name))) != nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lib.release();
|
||||
}
|
||||
|
||||
void dynld_close(void *handle)
|
||||
{
|
||||
delete reinterpret_cast<QLibrary*>(handle);
|
||||
}
|
||||
|
||||
void joystick_init(void) {}
|
||||
void joystick_close(void) {}
|
||||
void joystick_process(void) {}
|
||||
void startblit()
|
||||
{
|
||||
blitmx.lock();
|
||||
}
|
||||
|
||||
void endblit()
|
||||
{
|
||||
blitmx.unlock();
|
||||
}
|
||||
|
||||
}
|
743
src/qt/qt_sdl.c
Normal file
743
src/qt/qt_sdl.c
Normal file
@ -0,0 +1,743 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Rendering module for libSDL2
|
||||
*
|
||||
* NOTE: Given all the problems reported with FULLSCREEN use of SDL,
|
||||
* we will not use that, but, instead, use a new window which
|
||||
* coverrs the entire desktop.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Michael Dr<EFBFBD>ing, <michael@drueing.de>
|
||||
*
|
||||
* Copyright 2018-2020 Fred N. van Kempen.
|
||||
* Copyright 2018-2020 Michael Dr<EFBFBD>ing.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with
|
||||
* or without modification, are permitted provided that the
|
||||
* following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the entire
|
||||
* above notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names
|
||||
* of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
/* This #undef is needed because a SDL include header redefines HAVE_STDARG_H. */
|
||||
#undef HAVE_STDARG_H
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/mouse.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/plat_dynld.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/ui.h>
|
||||
#include <86box/version.h>
|
||||
|
||||
#include "qt_sdl.h"
|
||||
|
||||
#define RENDERER_FULL_SCREEN 1
|
||||
#define RENDERER_HARDWARE 2
|
||||
#define RENDERER_OPENGL 4
|
||||
|
||||
|
||||
static SDL_Window *sdl_win = NULL;
|
||||
static SDL_Renderer *sdl_render = NULL;
|
||||
static SDL_Texture *sdl_tex = NULL;
|
||||
static int sdl_w, sdl_h;
|
||||
static int sdl_fs, sdl_flags = -1;
|
||||
static int cur_w, cur_h;
|
||||
static int cur_ww = 0, cur_wh = 0;
|
||||
static volatile int sdl_enabled = 0;
|
||||
static SDL_mutex* sdl_mutex = NULL;
|
||||
static int blit_w = 0, blit_h = 0, blit_tex_updated = 0;
|
||||
|
||||
static const uint16_t sdl_to_xt[0x200] =
|
||||
{
|
||||
[SDL_SCANCODE_ESCAPE] = 0x01,
|
||||
[SDL_SCANCODE_1] = 0x02,
|
||||
[SDL_SCANCODE_2] = 0x03,
|
||||
[SDL_SCANCODE_3] = 0x04,
|
||||
[SDL_SCANCODE_4] = 0x05,
|
||||
[SDL_SCANCODE_5] = 0x06,
|
||||
[SDL_SCANCODE_6] = 0x07,
|
||||
[SDL_SCANCODE_7] = 0x08,
|
||||
[SDL_SCANCODE_8] = 0x09,
|
||||
[SDL_SCANCODE_9] = 0x0A,
|
||||
[SDL_SCANCODE_0] = 0x0B,
|
||||
[SDL_SCANCODE_MINUS] = 0x0C,
|
||||
[SDL_SCANCODE_EQUALS] = 0x0D,
|
||||
[SDL_SCANCODE_BACKSPACE] = 0x0E,
|
||||
[SDL_SCANCODE_TAB] = 0x0F,
|
||||
[SDL_SCANCODE_Q] = 0x10,
|
||||
[SDL_SCANCODE_W] = 0x11,
|
||||
[SDL_SCANCODE_E] = 0x12,
|
||||
[SDL_SCANCODE_R] = 0x13,
|
||||
[SDL_SCANCODE_T] = 0x14,
|
||||
[SDL_SCANCODE_Y] = 0x15,
|
||||
[SDL_SCANCODE_U] = 0x16,
|
||||
[SDL_SCANCODE_I] = 0x17,
|
||||
[SDL_SCANCODE_O] = 0x18,
|
||||
[SDL_SCANCODE_P] = 0x19,
|
||||
[SDL_SCANCODE_LEFTBRACKET] = 0x1A,
|
||||
[SDL_SCANCODE_RIGHTBRACKET] = 0x1B,
|
||||
[SDL_SCANCODE_RETURN] = 0x1C,
|
||||
[SDL_SCANCODE_LCTRL] = 0x1D,
|
||||
[SDL_SCANCODE_A] = 0x1E,
|
||||
[SDL_SCANCODE_S] = 0x1F,
|
||||
[SDL_SCANCODE_D] = 0x20,
|
||||
[SDL_SCANCODE_F] = 0x21,
|
||||
[SDL_SCANCODE_G] = 0x22,
|
||||
[SDL_SCANCODE_H] = 0x23,
|
||||
[SDL_SCANCODE_J] = 0x24,
|
||||
[SDL_SCANCODE_K] = 0x25,
|
||||
[SDL_SCANCODE_L] = 0x26,
|
||||
[SDL_SCANCODE_SEMICOLON] = 0x27,
|
||||
[SDL_SCANCODE_APOSTROPHE] = 0x28,
|
||||
[SDL_SCANCODE_GRAVE] = 0x29,
|
||||
[SDL_SCANCODE_LSHIFT] = 0x2A,
|
||||
[SDL_SCANCODE_BACKSLASH] = 0x2B,
|
||||
[SDL_SCANCODE_Z] = 0x2C,
|
||||
[SDL_SCANCODE_X] = 0x2D,
|
||||
[SDL_SCANCODE_C] = 0x2E,
|
||||
[SDL_SCANCODE_V] = 0x2F,
|
||||
[SDL_SCANCODE_B] = 0x30,
|
||||
[SDL_SCANCODE_N] = 0x31,
|
||||
[SDL_SCANCODE_M] = 0x32,
|
||||
[SDL_SCANCODE_COMMA] = 0x33,
|
||||
[SDL_SCANCODE_PERIOD] = 0x34,
|
||||
[SDL_SCANCODE_SLASH] = 0x35,
|
||||
[SDL_SCANCODE_RSHIFT] = 0x36,
|
||||
[SDL_SCANCODE_KP_MULTIPLY] = 0x37,
|
||||
[SDL_SCANCODE_LALT] = 0x38,
|
||||
[SDL_SCANCODE_SPACE] = 0x39,
|
||||
[SDL_SCANCODE_CAPSLOCK] = 0x3A,
|
||||
[SDL_SCANCODE_F1] = 0x3B,
|
||||
[SDL_SCANCODE_F2] = 0x3C,
|
||||
[SDL_SCANCODE_F3] = 0x3D,
|
||||
[SDL_SCANCODE_F4] = 0x3E,
|
||||
[SDL_SCANCODE_F5] = 0x3F,
|
||||
[SDL_SCANCODE_F6] = 0x40,
|
||||
[SDL_SCANCODE_F7] = 0x41,
|
||||
[SDL_SCANCODE_F8] = 0x42,
|
||||
[SDL_SCANCODE_F9] = 0x43,
|
||||
[SDL_SCANCODE_F10] = 0x44,
|
||||
[SDL_SCANCODE_NUMLOCKCLEAR] = 0x45,
|
||||
[SDL_SCANCODE_SCROLLLOCK] = 0x46,
|
||||
[SDL_SCANCODE_HOME] = 0x147,
|
||||
[SDL_SCANCODE_UP] = 0x148,
|
||||
[SDL_SCANCODE_PAGEUP] = 0x149,
|
||||
[SDL_SCANCODE_KP_MINUS] = 0x4A,
|
||||
[SDL_SCANCODE_LEFT] = 0x14B,
|
||||
[SDL_SCANCODE_KP_5] = 0x4C,
|
||||
[SDL_SCANCODE_RIGHT] = 0x14D,
|
||||
[SDL_SCANCODE_KP_PLUS] = 0x4E,
|
||||
[SDL_SCANCODE_END] = 0x14F,
|
||||
[SDL_SCANCODE_DOWN] = 0x150,
|
||||
[SDL_SCANCODE_PAGEDOWN] = 0x151,
|
||||
[SDL_SCANCODE_INSERT] = 0x152,
|
||||
[SDL_SCANCODE_DELETE] = 0x153,
|
||||
[SDL_SCANCODE_F11] = 0x57,
|
||||
[SDL_SCANCODE_F12] = 0x58,
|
||||
|
||||
[SDL_SCANCODE_KP_ENTER] = 0x11c,
|
||||
[SDL_SCANCODE_RCTRL] = 0x11d,
|
||||
[SDL_SCANCODE_KP_DIVIDE] = 0x135,
|
||||
[SDL_SCANCODE_RALT] = 0x138,
|
||||
[SDL_SCANCODE_KP_9] = 0x49,
|
||||
[SDL_SCANCODE_KP_8] = 0x48,
|
||||
[SDL_SCANCODE_KP_7] = 0x47,
|
||||
[SDL_SCANCODE_KP_6] = 0x4D,
|
||||
[SDL_SCANCODE_KP_4] = 0x4B,
|
||||
[SDL_SCANCODE_KP_3] = 0x51,
|
||||
[SDL_SCANCODE_KP_2] = 0x50,
|
||||
[SDL_SCANCODE_KP_1] = 0x4F,
|
||||
[SDL_SCANCODE_KP_0] = 0x52,
|
||||
[SDL_SCANCODE_KP_PERIOD] = 0x53,
|
||||
|
||||
[SDL_SCANCODE_LGUI] = 0x15B,
|
||||
[SDL_SCANCODE_RGUI] = 0x15C,
|
||||
[SDL_SCANCODE_APPLICATION] = 0x15D,
|
||||
[SDL_SCANCODE_PRINTSCREEN] = 0x137,
|
||||
[SDL_SCANCODE_NONUSBACKSLASH] = 0x56,
|
||||
};
|
||||
|
||||
typedef struct mouseinputdata
|
||||
{
|
||||
int deltax, deltay, deltaz;
|
||||
int mousebuttons;
|
||||
} mouseinputdata;
|
||||
static mouseinputdata mousedata;
|
||||
|
||||
// #define ENABLE_SDL_LOG 3
|
||||
#ifdef ENABLE_SDL_LOG
|
||||
int sdl_do_log = ENABLE_SDL_LOG;
|
||||
|
||||
static void
|
||||
sdl_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (sdl_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define sdl_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
sdl_integer_scale(double *d, double *g)
|
||||
{
|
||||
double ratio;
|
||||
|
||||
if (*d > *g) {
|
||||
ratio = floor(*d / *g);
|
||||
*d = *g * ratio;
|
||||
} else {
|
||||
ratio = ceil(*d / *g);
|
||||
*d = *g / ratio;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sdl_stretch(int *w, int *h, int *x, int *y)
|
||||
{
|
||||
double hw, gw, hh, gh, dx, dy, dw, dh, gsr, hsr;
|
||||
|
||||
hw = (double) sdl_w;
|
||||
hh = (double) sdl_h;
|
||||
gw = (double) *w;
|
||||
gh = (double) *h;
|
||||
hsr = hw / hh;
|
||||
|
||||
switch (video_fullscreen_scale) {
|
||||
case FULLSCR_SCALE_FULL:
|
||||
default:
|
||||
*w = sdl_w;
|
||||
*h = sdl_h;
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
break;
|
||||
case FULLSCR_SCALE_43:
|
||||
case FULLSCR_SCALE_KEEPRATIO:
|
||||
if (video_fullscreen_scale == FULLSCR_SCALE_43)
|
||||
gsr = 4.0 / 3.0;
|
||||
else
|
||||
gsr = gw / gh;
|
||||
if (gsr <= hsr) {
|
||||
dw = hh * gsr;
|
||||
dh = hh;
|
||||
} else {
|
||||
dw = hw;
|
||||
dh = hw / gsr;
|
||||
}
|
||||
dx = (hw - dw) / 2.0;
|
||||
dy = (hh - dh) / 2.0;
|
||||
*w = (int) dw;
|
||||
*h = (int) dh;
|
||||
*x = (int) dx;
|
||||
*y = (int) dy;
|
||||
break;
|
||||
case FULLSCR_SCALE_INT:
|
||||
gsr = gw / gh;
|
||||
if (gsr <= hsr) {
|
||||
dw = hh * gsr;
|
||||
dh = hh;
|
||||
} else {
|
||||
dw = hw;
|
||||
dh = hw / gsr;
|
||||
}
|
||||
sdl_integer_scale(&dw, &gw);
|
||||
sdl_integer_scale(&dh, &gh);
|
||||
dx = (hw - dw) / 2.0;
|
||||
dy = (hh - dh) / 2.0;
|
||||
*w = (int) dw;
|
||||
*h = (int) dh;
|
||||
*x = (int) dx;
|
||||
*y = (int) dy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sdl_blit(int x, int y, int w, int h)
|
||||
{
|
||||
void *pixeldata;
|
||||
int pitch;
|
||||
|
||||
if (!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) {
|
||||
video_blit_complete();
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_LockMutex(sdl_mutex);
|
||||
SDL_LockTexture(sdl_tex, 0, &pixeldata, &pitch);
|
||||
|
||||
video_copy(pixeldata, &(buffer32->line[y][x]), h * (2048 + 64) * sizeof(uint32_t));
|
||||
|
||||
if (screenshots)
|
||||
video_screenshot((uint32_t *) pixeldata, 0, 0, (2048 + 64));
|
||||
|
||||
blit_w = w;
|
||||
blit_h = h;
|
||||
blit_tex_updated = 1;
|
||||
|
||||
SDL_UnlockTexture(sdl_tex);
|
||||
SDL_UnlockMutex(sdl_mutex);
|
||||
video_blit_complete();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sdl_destroy_window(void)
|
||||
{
|
||||
if (sdl_win != NULL) {
|
||||
SDL_DestroyWindow(sdl_win);
|
||||
sdl_win = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sdl_destroy_texture(void)
|
||||
{
|
||||
if (sdl_tex != NULL) {
|
||||
SDL_DestroyTexture(sdl_tex);
|
||||
sdl_tex = NULL;
|
||||
}
|
||||
|
||||
/* SDL_DestroyRenderer also automatically destroys all associated textures. */
|
||||
if (sdl_render != NULL) {
|
||||
SDL_DestroyRenderer(sdl_render);
|
||||
sdl_render = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sdl_close(void)
|
||||
{
|
||||
if (sdl_mutex != NULL)
|
||||
SDL_LockMutex(sdl_mutex);
|
||||
|
||||
/* Unregister our renderer! */
|
||||
video_setblit(NULL);
|
||||
|
||||
if (sdl_enabled)
|
||||
sdl_enabled = 0;
|
||||
|
||||
if (sdl_mutex != NULL) {
|
||||
SDL_DestroyMutex(sdl_mutex);
|
||||
sdl_mutex = NULL;
|
||||
}
|
||||
|
||||
sdl_destroy_texture();
|
||||
sdl_destroy_window();
|
||||
|
||||
/* Quit. */
|
||||
SDL_Quit();
|
||||
sdl_flags = -1;
|
||||
}
|
||||
|
||||
static void sdl_select_best_hw_driver(void) {
|
||||
int i;
|
||||
SDL_RendererInfo renderInfo;
|
||||
|
||||
for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
|
||||
SDL_GetRenderDriverInfo(i, &renderInfo);
|
||||
if (renderInfo.flags & SDL_RENDERER_ACCELERATED) {
|
||||
SDL_SetHint(SDL_HINT_RENDER_DRIVER, renderInfo.name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sdl_init_texture(void)
|
||||
{
|
||||
if (sdl_flags & RENDERER_HARDWARE) {
|
||||
sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_ACCELERATED);
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0");
|
||||
} else {
|
||||
sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_SOFTWARE);
|
||||
}
|
||||
|
||||
sdl_tex = SDL_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STREAMING, (2048 + 64), (2048 + 64));
|
||||
|
||||
if (sdl_render == NULL) {
|
||||
sdl_log("SDL: unable to SDL_CreateRenderer (%s)\n", SDL_GetError());
|
||||
}
|
||||
if (sdl_tex == NULL) {
|
||||
sdl_log("SDL: unable to SDL_CreateTexture (%s)\n", SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sdl_reinit_texture(void)
|
||||
{
|
||||
if (sdl_flags == -1)
|
||||
return;
|
||||
|
||||
sdl_destroy_texture();
|
||||
sdl_init_texture();
|
||||
}
|
||||
|
||||
|
||||
void sdl_set_fs(int fs) {
|
||||
SDL_SetWindowFullscreen(sdl_win, fs ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
||||
SDL_SetRelativeMouseMode((SDL_bool)mouse_capture);
|
||||
|
||||
sdl_fs = fs;
|
||||
|
||||
if (fs) {
|
||||
sdl_flags |= RENDERER_FULL_SCREEN;
|
||||
} else {
|
||||
sdl_flags &= ~RENDERER_FULL_SCREEN;
|
||||
}
|
||||
|
||||
sdl_reinit_texture();
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
sdl_init_common(void* win, int flags)
|
||||
{
|
||||
wchar_t temp[128];
|
||||
SDL_version ver;
|
||||
|
||||
sdl_log("SDL: init (fs=%d)\n", 0);
|
||||
|
||||
/* Get and log the version of the DLL we are using. */
|
||||
SDL_GetVersion(&ver);
|
||||
sdl_log("SDL: version %d.%d.%d\n", ver.major, ver.minor, ver.patch);
|
||||
|
||||
/* Initialize the SDL system. */
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
sdl_log("SDL: initialization failed (%s)\n", SDL_GetError());
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (flags & RENDERER_HARDWARE) {
|
||||
if (flags & RENDERER_OPENGL)
|
||||
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "OpenGL");
|
||||
else
|
||||
sdl_select_best_hw_driver();
|
||||
}
|
||||
|
||||
/* Get the size of the (current) desktop. */
|
||||
SDL_DisplayMode dm;
|
||||
if (SDL_GetDesktopDisplayMode(0, &dm) != 0) {
|
||||
sdl_log("SDL: SDL_GetDesktopDisplayMode failed (%s)\n", SDL_GetError());
|
||||
return(0);
|
||||
}
|
||||
sdl_w = dm.w;
|
||||
sdl_h = dm.h;
|
||||
sdl_flags = flags;
|
||||
|
||||
sdl_win = SDL_CreateWindow("86Box renderer", 640, 480, 100, 100, sdl_flags);
|
||||
if (sdl_win == NULL) {
|
||||
sdl_log("SDL: unable to CreateWindowFrom (%s)\n", SDL_GetError());
|
||||
}
|
||||
sdl_init_texture();
|
||||
sdl_set_fs(video_fullscreen & 1);
|
||||
|
||||
/* Make sure we get a clean exit. */
|
||||
atexit(sdl_close);
|
||||
|
||||
/* Register our renderer! */
|
||||
video_setblit(sdl_blit);
|
||||
|
||||
sdl_enabled = 1;
|
||||
sdl_mutex = SDL_CreateMutex();
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sdl_inits(void* win)
|
||||
{
|
||||
return sdl_init_common(win, 0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sdl_inith(void* win)
|
||||
{
|
||||
return sdl_init_common(win, RENDERER_HARDWARE);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sdl_initho(void* win)
|
||||
{
|
||||
return sdl_init_common(win, RENDERER_HARDWARE | RENDERER_OPENGL);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sdl_pause(void)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sdl_resize(int w, int h)
|
||||
{
|
||||
int ww = 0, wh = 0;
|
||||
|
||||
if (video_fullscreen & 2)
|
||||
return;
|
||||
|
||||
if ((w == cur_w) && (h == cur_h))
|
||||
return;
|
||||
|
||||
SDL_LockMutex(sdl_mutex);
|
||||
|
||||
ww = w;
|
||||
wh = h;
|
||||
|
||||
if (sdl_fs) {
|
||||
// sdl_stretch(&ww, &wh, &wx, &wy);
|
||||
// MoveWindow(hwndRender, wx, wy, ww, wh, TRUE);
|
||||
}
|
||||
|
||||
cur_w = w;
|
||||
cur_h = h;
|
||||
|
||||
cur_ww = ww;
|
||||
cur_wh = wh;
|
||||
|
||||
SDL_SetWindowSize(sdl_win, cur_ww, cur_wh);
|
||||
sdl_reinit_texture();
|
||||
|
||||
SDL_UnlockMutex(sdl_mutex);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sdl_enable(int enable)
|
||||
{
|
||||
if (sdl_flags == -1)
|
||||
return;
|
||||
|
||||
SDL_LockMutex(sdl_mutex);
|
||||
sdl_enabled = !!enable;
|
||||
|
||||
if (enable == 1) {
|
||||
SDL_SetWindowSize(sdl_win, cur_ww, cur_wh);
|
||||
sdl_reinit_texture();
|
||||
}
|
||||
|
||||
SDL_UnlockMutex(sdl_mutex);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sdl_reload(void)
|
||||
{
|
||||
if (sdl_flags & RENDERER_HARDWARE) {
|
||||
SDL_LockMutex(sdl_mutex);
|
||||
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0");
|
||||
sdl_reinit_texture();
|
||||
|
||||
SDL_UnlockMutex(sdl_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static int mouse_inside = 0;
|
||||
enum sdl_main_status sdl_main() {
|
||||
int ret = SdlMainOk;
|
||||
SDL_Rect r_src;
|
||||
SDL_Event event;
|
||||
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
switch(event.type)
|
||||
{
|
||||
case SDL_QUIT:
|
||||
ret = SdlMainQuit;
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
{
|
||||
if (mouse_capture || video_fullscreen)
|
||||
{
|
||||
if (event.wheel.direction == SDL_MOUSEWHEEL_FLIPPED)
|
||||
{
|
||||
event.wheel.x *= -1;
|
||||
event.wheel.y *= -1;
|
||||
}
|
||||
mousedata.deltaz = event.wheel.y;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEMOTION:
|
||||
{
|
||||
if (mouse_capture || video_fullscreen)
|
||||
{
|
||||
mousedata.deltax += event.motion.xrel;
|
||||
mousedata.deltay += event.motion.yrel;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
{
|
||||
if ((event.button.button == SDL_BUTTON_LEFT)
|
||||
&& !(mouse_capture || video_fullscreen)
|
||||
&& event.button.state == SDL_RELEASED
|
||||
&& mouse_inside)
|
||||
{
|
||||
plat_mouse_capture(1);
|
||||
break;
|
||||
}
|
||||
if (mouse_get_buttons() < 3 && event.button.button == SDL_BUTTON_MIDDLE && !video_fullscreen)
|
||||
{
|
||||
plat_mouse_capture(0);
|
||||
break;
|
||||
}
|
||||
if (mouse_capture || video_fullscreen)
|
||||
{
|
||||
int buttonmask = 0;
|
||||
|
||||
switch(event.button.button)
|
||||
{
|
||||
case SDL_BUTTON_LEFT:
|
||||
buttonmask = 1;
|
||||
break;
|
||||
case SDL_BUTTON_RIGHT:
|
||||
buttonmask = 2;
|
||||
break;
|
||||
case SDL_BUTTON_MIDDLE:
|
||||
buttonmask = 4;
|
||||
break;
|
||||
}
|
||||
if (event.button.state == SDL_PRESSED)
|
||||
{
|
||||
mousedata.mousebuttons |= buttonmask;
|
||||
}
|
||||
else mousedata.mousebuttons &= ~buttonmask;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_RENDER_DEVICE_RESET:
|
||||
case SDL_RENDER_TARGETS_RESET:
|
||||
{
|
||||
sdl_reinit_texture();
|
||||
break;
|
||||
}
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
{
|
||||
uint16_t xtkey = 0;
|
||||
switch(event.key.keysym.scancode)
|
||||
{
|
||||
default:
|
||||
xtkey = sdl_to_xt[event.key.keysym.scancode];
|
||||
break;
|
||||
}
|
||||
keyboard_input(event.key.state == SDL_PRESSED, xtkey);
|
||||
}
|
||||
break;
|
||||
case SDL_WINDOWEVENT:
|
||||
{
|
||||
switch (event.window.event)
|
||||
{
|
||||
case SDL_WINDOWEVENT_ENTER:
|
||||
mouse_inside = 1;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_LEAVE:
|
||||
mouse_inside = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (blit_tex_updated > 0) {
|
||||
SDL_LockMutex(sdl_mutex);
|
||||
int status = SDL_RenderClear(sdl_render);
|
||||
if (status) {
|
||||
sdl_log("SDL: unable to SDL_RenderClear (%s)\n", SDL_GetError());
|
||||
}
|
||||
|
||||
r_src.x = 0;
|
||||
r_src.y = 0;
|
||||
r_src.w = blit_w;
|
||||
r_src.h = blit_h;
|
||||
|
||||
status = SDL_RenderCopy(sdl_render, sdl_tex, &r_src, 0);
|
||||
if (status) {
|
||||
sdl_log("SDL: unable to copy texture to renderer (%s)\n", SDL_GetError());
|
||||
}
|
||||
|
||||
SDL_RenderPresent(sdl_render);
|
||||
blit_tex_updated = 0;
|
||||
SDL_UnlockMutex(sdl_mutex);
|
||||
}
|
||||
|
||||
if (mouse_capture && keyboard_ismsexit()) {
|
||||
plat_mouse_capture(0);
|
||||
}
|
||||
if (video_fullscreen && keyboard_isfsexit()) {
|
||||
plat_setfullscreen(0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sdl_mouse_capture(int on) {
|
||||
SDL_SetRelativeMouseMode((SDL_bool)on);
|
||||
}
|
||||
|
||||
void sdl_mouse_poll() {
|
||||
mouse_x = mousedata.deltax;
|
||||
mouse_y = mousedata.deltay;
|
||||
mouse_z = mousedata.deltaz;
|
||||
mousedata.deltax = mousedata.deltay = mousedata.deltaz = 0;
|
||||
mouse_buttons = mousedata.mousebuttons;
|
||||
}
|
73
src/qt/qt_sdl.h
Normal file
73
src/qt/qt_sdl.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Definitions for the libSDL2 rendering module.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Michael Drüing, <michael@drueing.de>
|
||||
*
|
||||
* Copyright 2018,2019 Fred N. van Kempen.
|
||||
* Copyright 2018,2019 Michael Drüing.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with
|
||||
* or without modification, are permitted provided that the
|
||||
* following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the entire
|
||||
* above notice, this list of conditions and the following
|
||||
* disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the
|
||||
* following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names
|
||||
* of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef WIN_SDL_H
|
||||
# define WIN_SDL_H
|
||||
|
||||
extern void* sdl_win_handle;
|
||||
extern void sdl_close(void);
|
||||
extern int sdl_inits();
|
||||
extern int sdl_inith();
|
||||
extern int sdl_initho();
|
||||
extern int sdl_pause(void);
|
||||
extern void sdl_resize(int w, int h);
|
||||
extern void sdl_enable(int enable);
|
||||
extern void sdl_set_fs(int fs);
|
||||
extern void sdl_reload(void);
|
||||
|
||||
enum sdl_main_status {
|
||||
SdlMainOk,
|
||||
SdlMainQuit,
|
||||
};
|
||||
|
||||
extern enum sdl_main_status sdl_main();
|
||||
|
||||
extern void sdl_mouse_capture(int on);
|
||||
extern void sdl_mouse_poll();
|
||||
|
||||
#endif /*WIN_SDL_H*/
|
131
src/qt/qt_settings.cpp
Normal file
131
src/qt/qt_settings.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
#include "qt_settings.hpp"
|
||||
#include "ui_qt_settings.h"
|
||||
|
||||
#include "qt_settingsmachine.hpp"
|
||||
#include "qt_settingsdisplay.hpp"
|
||||
#include "qt_settingsinput.hpp"
|
||||
#include "qt_settingssound.hpp"
|
||||
#include "qt_settingsnetwork.hpp"
|
||||
#include "qt_settingsports.hpp"
|
||||
#include "qt_settingsstoragecontrollers.hpp"
|
||||
#include "qt_settingsharddisks.hpp"
|
||||
#include "qt_settingsfloppycdrom.hpp"
|
||||
#include "qt_settingsotherremovable.hpp"
|
||||
#include "qt_settingsotherperipherals.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
class SettingsModel : public QAbstractListModel {
|
||||
public:
|
||||
SettingsModel(QObject* parent) : QAbstractListModel(parent) {}
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
private:
|
||||
QStringList pages = {
|
||||
"Machine",
|
||||
"Display",
|
||||
"Input Devices",
|
||||
"Sound",
|
||||
"Network",
|
||||
"Ports (COM & LPT)",
|
||||
"Storage Controllers",
|
||||
"Hard Disks",
|
||||
"Floppy & CD-ROM Drives",
|
||||
"Other Removable Devices",
|
||||
"Other Peripherals",
|
||||
};
|
||||
QStringList page_icons = {
|
||||
"machine",
|
||||
"display",
|
||||
"input_devices",
|
||||
"sound",
|
||||
"network",
|
||||
"ports",
|
||||
"storage_controllers",
|
||||
"hard_disk",
|
||||
"floppy_and_cdrom_drives",
|
||||
"other_removable_devices",
|
||||
"other_peripherals",
|
||||
};
|
||||
};
|
||||
|
||||
QVariant SettingsModel::data(const QModelIndex &index, int role) const {
|
||||
Q_ASSERT(checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::ParentIsInvalid));
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return pages.at(index.row());
|
||||
case Qt::DecorationRole:
|
||||
return QIcon(QString(":/settings/win/icons/%1.ico").arg(page_icons[index.row()]));
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
int SettingsModel::rowCount(const QModelIndex &parent) const {
|
||||
(void) parent;
|
||||
return pages.size();
|
||||
}
|
||||
|
||||
Settings::Settings(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::Settings)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->listView->setModel(new SettingsModel(this));
|
||||
|
||||
machine = new SettingsMachine(this);
|
||||
display = new SettingsDisplay(this);
|
||||
input = new SettingsInput(this);
|
||||
sound = new SettingsSound(this);
|
||||
network = new SettingsNetwork(this);
|
||||
ports = new SettingsPorts(this);
|
||||
storageControllers = new SettingsStorageControllers(this);
|
||||
harddisks = new SettingsHarddisks(this);
|
||||
floppyCdrom = new SettingsFloppyCDROM(this);
|
||||
otherRemovable = new SettingsOtherRemovable(this);
|
||||
otherPeripherals = new SettingsOtherPeripherals(this);
|
||||
|
||||
ui->stackedWidget->addWidget(machine);
|
||||
ui->stackedWidget->addWidget(display);
|
||||
ui->stackedWidget->addWidget(input);
|
||||
ui->stackedWidget->addWidget(sound);
|
||||
ui->stackedWidget->addWidget(network);
|
||||
ui->stackedWidget->addWidget(ports);
|
||||
ui->stackedWidget->addWidget(storageControllers);
|
||||
ui->stackedWidget->addWidget(harddisks);
|
||||
ui->stackedWidget->addWidget(floppyCdrom);
|
||||
ui->stackedWidget->addWidget(otherRemovable);
|
||||
ui->stackedWidget->addWidget(otherPeripherals);
|
||||
|
||||
connect(machine, &SettingsMachine::currentMachineChanged, display, &SettingsDisplay::onCurrentMachineChanged);
|
||||
connect(machine, &SettingsMachine::currentMachineChanged, input, &SettingsInput::onCurrentMachineChanged);
|
||||
connect(machine, &SettingsMachine::currentMachineChanged, sound, &SettingsSound::onCurrentMachineChanged);
|
||||
connect(machine, &SettingsMachine::currentMachineChanged, network, &SettingsNetwork::onCurrentMachineChanged);
|
||||
connect(machine, &SettingsMachine::currentMachineChanged, storageControllers, &SettingsStorageControllers::onCurrentMachineChanged);
|
||||
|
||||
connect(ui->listView->selectionModel(), &QItemSelectionModel::currentChanged, this, [this](const QModelIndex ¤t, const QModelIndex &previous) {
|
||||
ui->stackedWidget->setCurrentIndex(current.row());
|
||||
});
|
||||
}
|
||||
|
||||
Settings::~Settings()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void Settings::save() {
|
||||
machine->save();
|
||||
display->save();
|
||||
input->save();
|
||||
sound->save();
|
||||
network->save();
|
||||
ports->save();
|
||||
storageControllers->save();
|
||||
harddisks->save();
|
||||
floppyCdrom->save();
|
||||
otherRemovable->save();
|
||||
otherPeripherals->save();
|
||||
}
|
46
src/qt/qt_settings.hpp
Normal file
46
src/qt/qt_settings.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef QT_SETTINGS_HPP
|
||||
#define QT_SETTINGS_HPP
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class Settings;
|
||||
}
|
||||
|
||||
class SettingsMachine;
|
||||
class SettingsDisplay;
|
||||
class SettingsInput;
|
||||
class SettingsSound;
|
||||
class SettingsNetwork;
|
||||
class SettingsPorts;
|
||||
class SettingsStorageControllers;
|
||||
class SettingsHarddisks;
|
||||
class SettingsFloppyCDROM;
|
||||
class SettingsOtherRemovable;
|
||||
class SettingsOtherPeripherals;
|
||||
|
||||
class Settings : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Settings(QWidget *parent = nullptr);
|
||||
~Settings();
|
||||
void save();
|
||||
|
||||
private:
|
||||
Ui::Settings *ui;
|
||||
SettingsMachine* machine;
|
||||
SettingsDisplay* display;
|
||||
SettingsInput* input;
|
||||
SettingsSound* sound;
|
||||
SettingsNetwork* network;
|
||||
SettingsPorts* ports;
|
||||
SettingsStorageControllers* storageControllers;
|
||||
SettingsHarddisks* harddisks;
|
||||
SettingsFloppyCDROM* floppyCdrom;
|
||||
SettingsOtherRemovable* otherRemovable;
|
||||
SettingsOtherPeripherals* otherPeripherals;
|
||||
};
|
||||
|
||||
#endif // QT_SETTINGS_HPP
|
87
src/qt/qt_settings.ui
Normal file
87
src/qt/qt_settings.ui
Normal file
@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Settings</class>
|
||||
<widget class="QDialog" name="Settings">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>900</width>
|
||||
<height>595</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>86Box Settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,3">
|
||||
<item>
|
||||
<widget class="QListView" name="listView"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Settings</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Settings</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
105
src/qt/qt_settingsdisplay.cpp
Normal file
105
src/qt/qt_settingsdisplay.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
#include "qt_settingsdisplay.hpp"
|
||||
#include "ui_qt_settingsdisplay.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/video.h>
|
||||
}
|
||||
|
||||
#include "qt_deviceconfig.hpp"
|
||||
#include "qt_models_common.hpp"
|
||||
|
||||
SettingsDisplay::SettingsDisplay(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::SettingsDisplay)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
onCurrentMachineChanged(machine);
|
||||
}
|
||||
|
||||
SettingsDisplay::~SettingsDisplay()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SettingsDisplay::save() {
|
||||
gfxcard = ui->comboBoxVideo->currentData().toInt();
|
||||
voodoo_enabled = ui->checkBoxVoodoo->isChecked() ? 1 : 0;
|
||||
}
|
||||
|
||||
void SettingsDisplay::onCurrentMachineChanged(int machineId) {
|
||||
// win_settings_video_proc, WM_INITDIALOG
|
||||
this->machineId = machineId;
|
||||
|
||||
auto* machine = &machines[machineId];
|
||||
auto* model = ui->comboBoxVideo->model();
|
||||
auto removeRows = model->rowCount();
|
||||
|
||||
int c = 0;
|
||||
int selectedRow = 0;
|
||||
while (true) {
|
||||
/* Skip "internal" if machine doesn't have it. */
|
||||
if ((c == 1) && !(machine->flags & MACHINE_VIDEO)) {
|
||||
c++;
|
||||
continue;
|
||||
}
|
||||
|
||||
const device_t* video_dev = video_card_getdevice(c);
|
||||
QString name = DeviceConfig::DeviceName(video_dev, video_get_internal_name(c), 1);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (video_card_available(c) &&
|
||||
device_is_valid(video_dev, machine->flags)) {
|
||||
int row = Models::AddEntry(model, name, c);
|
||||
if (c == gfxcard) {
|
||||
selectedRow = row - removeRows;
|
||||
}
|
||||
}
|
||||
|
||||
c++;
|
||||
}
|
||||
model->removeRows(0, removeRows);
|
||||
|
||||
if (machine->flags & MACHINE_VIDEO_ONLY) {
|
||||
ui->comboBoxVideo->setEnabled(false);
|
||||
selectedRow = 1;
|
||||
} else {
|
||||
ui->comboBoxVideo->setEnabled(true);
|
||||
}
|
||||
ui->comboBoxVideo->setCurrentIndex(selectedRow);
|
||||
}
|
||||
|
||||
void SettingsDisplay::on_pushButtonConfigure_clicked() {
|
||||
auto* device = video_card_getdevice(ui->comboBoxVideo->currentData().toInt());
|
||||
DeviceConfig::ConfigureDevice(device);
|
||||
}
|
||||
|
||||
void SettingsDisplay::on_pushButtonConfigureVoodoo_clicked() {
|
||||
DeviceConfig::ConfigureDevice(&voodoo_device);
|
||||
}
|
||||
|
||||
void SettingsDisplay::on_comboBoxVideo_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
int videoCard = ui->comboBoxVideo->currentData().toInt();
|
||||
ui->pushButtonConfigure->setEnabled(video_card_has_config(videoCard) > 0);
|
||||
|
||||
bool machineHasPci = machines[machineId].flags & MACHINE_BUS_PCI;
|
||||
ui->checkBoxVoodoo->setEnabled(machineHasPci);
|
||||
if (machineHasPci) {
|
||||
ui->checkBoxVoodoo->setChecked(voodoo_enabled);
|
||||
}
|
||||
ui->pushButtonConfigureVoodoo->setEnabled(machineHasPci && ui->checkBoxVoodoo->isChecked());
|
||||
}
|
||||
|
||||
void SettingsDisplay::on_checkBoxVoodoo_stateChanged(int state) {
|
||||
ui->pushButtonConfigureVoodoo->setEnabled(state == Qt::Checked);
|
||||
}
|
34
src/qt/qt_settingsdisplay.hpp
Normal file
34
src/qt/qt_settingsdisplay.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef QT_SETTINGSDISPLAY_HPP
|
||||
#define QT_SETTINGSDISPLAY_HPP
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class SettingsDisplay;
|
||||
}
|
||||
|
||||
class SettingsDisplay : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsDisplay(QWidget *parent = nullptr);
|
||||
~SettingsDisplay();
|
||||
|
||||
void save();
|
||||
|
||||
public slots:
|
||||
void onCurrentMachineChanged(int machineId);
|
||||
|
||||
private slots:
|
||||
void on_checkBoxVoodoo_stateChanged(int state);
|
||||
void on_comboBoxVideo_currentIndexChanged(int index);
|
||||
void on_pushButtonConfigureVoodoo_clicked();
|
||||
void on_pushButtonConfigure_clicked();
|
||||
|
||||
private:
|
||||
Ui::SettingsDisplay *ui;
|
||||
int machineId = 0;
|
||||
};
|
||||
|
||||
#endif // QT_SETTINGSDISPLAY_HPP
|
77
src/qt/qt_settingsdisplay.ui
Normal file
77
src/qt/qt_settingsdisplay.ui
Normal file
@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SettingsDisplay</class>
|
||||
<widget class="QWidget" name="SettingsDisplay">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxVideo"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Video</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigure">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigureVoodoo">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBoxVoodoo">
|
||||
<property name="text">
|
||||
<string>Voodoo Graphics</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
217
src/qt/qt_settingsfloppycdrom.cpp
Normal file
217
src/qt/qt_settingsfloppycdrom.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
#include "qt_settingsfloppycdrom.hpp"
|
||||
#include "ui_qt_settingsfloppycdrom.h"
|
||||
|
||||
extern "C" {
|
||||
#include <86box/timer.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/cdrom.h>
|
||||
}
|
||||
|
||||
#include <QStandardItemModel>
|
||||
|
||||
#include "qt_models_common.hpp"
|
||||
#include "qt_harddrive_common.hpp"
|
||||
|
||||
static void setFloppyType(QAbstractItemModel* model, const QModelIndex& idx, int type) {
|
||||
QIcon icon;
|
||||
if (type == 0) {
|
||||
icon = QIcon(":/settings/win/icons/floppy_disabled.ico");
|
||||
} else if (type >= 1 && type <= 6) {
|
||||
icon = QIcon(":/settings/win/icons/floppy_525.ico");
|
||||
} else {
|
||||
icon = QIcon(":/settings/win/icons/floppy_35.ico");
|
||||
}
|
||||
|
||||
model->setData(idx, fdd_getname(type));
|
||||
model->setData(idx, type, Qt::UserRole);
|
||||
model->setData(idx, icon, Qt::DecorationRole);
|
||||
}
|
||||
|
||||
static void setCDROMBus(QAbstractItemModel* model, const QModelIndex& idx, uint8_t bus, uint8_t channel) {
|
||||
QIcon icon;
|
||||
switch (bus) {
|
||||
case CDROM_BUS_DISABLED:
|
||||
icon = QIcon(":/settings/win/icons/cdrom_disabled.ico");
|
||||
break;
|
||||
case CDROM_BUS_ATAPI:
|
||||
case CDROM_BUS_SCSI:
|
||||
icon = QIcon(":/settings/win/icons/cdrom.ico");
|
||||
break;
|
||||
}
|
||||
|
||||
auto i = idx.siblingAtColumn(0);
|
||||
model->setData(i, Harddrives::BusChannelName(bus, channel));
|
||||
model->setData(i, bus, Qt::UserRole);
|
||||
model->setData(i, channel, Qt::UserRole + 1);
|
||||
model->setData(i, icon, Qt::DecorationRole);
|
||||
}
|
||||
|
||||
static void setCDROMSpeed(QAbstractItemModel* model, const QModelIndex& idx, uint8_t speed) {
|
||||
auto i = idx.siblingAtColumn(1);
|
||||
model->setData(i, QString("%1x").arg(speed));
|
||||
model->setData(i, speed, Qt::UserRole);
|
||||
}
|
||||
|
||||
SettingsFloppyCDROM::SettingsFloppyCDROM(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::SettingsFloppyCDROM)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
auto* model = ui->comboBoxFloppyType->model();
|
||||
int i = 0;
|
||||
while (true) {
|
||||
QString name = fdd_getname(i);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
Models::AddEntry(model, name, i);
|
||||
++i;
|
||||
}
|
||||
|
||||
model = new QStandardItemModel(0, 3, this);
|
||||
ui->tableViewFloppy->setModel(model);
|
||||
model->setHeaderData(0, Qt::Horizontal, "Type");
|
||||
model->setHeaderData(1, Qt::Horizontal, "Turbo");
|
||||
model->setHeaderData(2, Qt::Horizontal, "Check BPB");
|
||||
|
||||
model->insertRows(0, FDD_NUM);
|
||||
/* Floppy drives category */
|
||||
for (int i = 0; i < FDD_NUM; i++) {
|
||||
auto idx = model->index(i, 0);
|
||||
int type = fdd_get_type(i);
|
||||
setFloppyType(model, idx, type);
|
||||
model->setData(idx.siblingAtColumn(1), fdd_get_turbo(i) > 0 ? "On" : "Off");
|
||||
model->setData(idx.siblingAtColumn(2), fdd_get_check_bpb(i) > 0 ? "On" : "Off");
|
||||
}
|
||||
|
||||
ui->tableViewFloppy->resizeColumnsToContents();
|
||||
ui->tableViewFloppy->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
|
||||
connect(ui->tableViewFloppy->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &SettingsFloppyCDROM::onFloppyRowChanged);
|
||||
ui->tableViewFloppy->setCurrentIndex(model->index(0, 0));
|
||||
|
||||
|
||||
Harddrives::populateRemovableBuses(ui->comboBoxBus->model());
|
||||
model = ui->comboBoxSpeed->model();
|
||||
for (int i = 0; i <= 72; i++) {
|
||||
Models::AddEntry(model, QString("%1x").arg(i), i);
|
||||
}
|
||||
|
||||
model = new QStandardItemModel(0, 2, this);
|
||||
ui->tableViewCDROM->setModel(model);
|
||||
model->setHeaderData(0, Qt::Horizontal, "Bus");
|
||||
model->setHeaderData(1, Qt::Horizontal, "Speed");
|
||||
model->insertRows(0, CDROM_NUM);
|
||||
for (int i = 0; i < CDROM_NUM; i++) {
|
||||
auto idx = model->index(i, 0);
|
||||
setCDROMBus(model, idx, cdrom[i].bus_type, cdrom[i].res);
|
||||
setCDROMSpeed(model, idx.siblingAtColumn(1), cdrom[i].speed);
|
||||
}
|
||||
ui->tableViewCDROM->resizeColumnsToContents();
|
||||
ui->tableViewCDROM->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
|
||||
connect(ui->tableViewCDROM->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &SettingsFloppyCDROM::onCDROMRowChanged);
|
||||
ui->tableViewCDROM->setCurrentIndex(model->index(0, 0));
|
||||
}
|
||||
|
||||
SettingsFloppyCDROM::~SettingsFloppyCDROM()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SettingsFloppyCDROM::save() {
|
||||
auto* model = ui->tableViewFloppy->model();
|
||||
for (int i = 0; i < FDD_NUM; i++) {
|
||||
fdd_set_type(i, model->index(i, 0).data(Qt::UserRole).toInt());
|
||||
fdd_set_turbo(i, model->index(i, 1).data() == "On" ? 1 : 0);
|
||||
fdd_set_check_bpb(i, model->index(i, 2).data() == "On" ? 1 : 0);
|
||||
}
|
||||
|
||||
/* Removable devices category */
|
||||
model = ui->tableViewCDROM->model();
|
||||
memset(cdrom, 0, sizeof(cdrom));
|
||||
for (int i = 0; i < CDROM_NUM; i++) {
|
||||
cdrom[i].bus_type = model->index(i, 0).data(Qt::UserRole).toUInt();
|
||||
cdrom[i].res = model->index(i, 0).data(Qt::UserRole + 1).toUInt();
|
||||
cdrom[i].speed = model->index(i, 1).data(Qt::UserRole).toUInt();
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsFloppyCDROM::onFloppyRowChanged(const QModelIndex ¤t) {
|
||||
int type = current.siblingAtColumn(0).data(Qt::UserRole).toInt();
|
||||
ui->comboBoxFloppyType->setCurrentIndex(type);
|
||||
ui->checkBoxTurboTimings->setChecked(current.siblingAtColumn(1).data() == "On");
|
||||
ui->checkBoxCheckBPB->setChecked(current.siblingAtColumn(2).data() == "On");
|
||||
}
|
||||
|
||||
void SettingsFloppyCDROM::onCDROMRowChanged(const QModelIndex ¤t) {
|
||||
uint8_t bus = current.siblingAtColumn(0).data(Qt::UserRole).toUInt();
|
||||
uint8_t channel = current.siblingAtColumn(0).data(Qt::UserRole + 1).toUInt();
|
||||
uint8_t speed = current.siblingAtColumn(1).data(Qt::UserRole).toUInt();
|
||||
|
||||
ui->comboBoxBus->setCurrentIndex(-1);
|
||||
auto* model = ui->comboBoxBus->model();
|
||||
auto match = model->match(model->index(0, 0), Qt::UserRole, bus);
|
||||
if (! match.isEmpty()) {
|
||||
ui->comboBoxBus->setCurrentIndex(match.first().row());
|
||||
}
|
||||
|
||||
model = ui->comboBoxChannel->model();
|
||||
match = model->match(model->index(0, 0), Qt::UserRole, channel);
|
||||
if (! match.isEmpty()) {
|
||||
ui->comboBoxChannel->setCurrentIndex(match.first().row());
|
||||
}
|
||||
ui->comboBoxSpeed->setCurrentIndex(speed);
|
||||
}
|
||||
|
||||
void SettingsFloppyCDROM::on_checkBoxTurboTimings_stateChanged(int arg1) {
|
||||
auto idx = ui->tableViewFloppy->selectionModel()->currentIndex();
|
||||
ui->tableViewFloppy->model()->setData(idx.siblingAtColumn(1), arg1 == Qt::Checked ? "On" : "Off");
|
||||
}
|
||||
|
||||
void SettingsFloppyCDROM::on_checkBoxCheckBPB_stateChanged(int arg1) {
|
||||
auto idx = ui->tableViewFloppy->selectionModel()->currentIndex();
|
||||
ui->tableViewFloppy->model()->setData(idx.siblingAtColumn(2), arg1 == Qt::Checked ? "On" : "Off");
|
||||
}
|
||||
|
||||
void SettingsFloppyCDROM::on_comboBoxFloppyType_activated(int index) {
|
||||
setFloppyType(ui->tableViewFloppy->model(), ui->tableViewFloppy->selectionModel()->currentIndex(), index);
|
||||
}
|
||||
|
||||
void SettingsFloppyCDROM::on_comboBoxBus_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int bus = ui->comboBoxBus->currentData().toInt();
|
||||
bool enabled = (bus != CDROM_BUS_DISABLED);
|
||||
ui->comboBoxChannel->setEnabled(enabled);
|
||||
ui->comboBoxSpeed->setEnabled(enabled);
|
||||
Harddrives::populateBusChannels(ui->comboBoxChannel->model(), bus);
|
||||
}
|
||||
|
||||
void SettingsFloppyCDROM::on_comboBoxSpeed_activated(int index) {
|
||||
auto idx = ui->tableViewCDROM->selectionModel()->currentIndex();
|
||||
setCDROMSpeed(ui->tableViewCDROM->model(), idx.siblingAtColumn(1), index);
|
||||
}
|
||||
|
||||
|
||||
void SettingsFloppyCDROM::on_comboBoxBus_activated(int) {
|
||||
setCDROMBus(
|
||||
ui->tableViewCDROM->model(),
|
||||
ui->tableViewCDROM->selectionModel()->currentIndex(),
|
||||
ui->comboBoxBus->currentData().toUInt(),
|
||||
ui->comboBoxChannel->currentData().toUInt());
|
||||
}
|
||||
|
||||
|
||||
void SettingsFloppyCDROM::on_comboBoxChannel_activated(int) {
|
||||
setCDROMBus(
|
||||
ui->tableViewCDROM->model(),
|
||||
ui->tableViewCDROM->selectionModel()->currentIndex(),
|
||||
ui->comboBoxBus->currentData().toUInt(),
|
||||
ui->comboBoxChannel->currentData().toUInt());
|
||||
}
|
||||
|
35
src/qt/qt_settingsfloppycdrom.hpp
Normal file
35
src/qt/qt_settingsfloppycdrom.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef QT_SETTINGSFLOPPYCDROM_HPP
|
||||
#define QT_SETTINGSFLOPPYCDROM_HPP
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class SettingsFloppyCDROM;
|
||||
}
|
||||
|
||||
class SettingsFloppyCDROM : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsFloppyCDROM(QWidget *parent = nullptr);
|
||||
~SettingsFloppyCDROM();
|
||||
|
||||
void save();
|
||||
|
||||
private slots:
|
||||
void on_comboBoxChannel_activated(int index);
|
||||
void on_comboBoxBus_activated(int index);
|
||||
void on_comboBoxSpeed_activated(int index);
|
||||
void on_comboBoxBus_currentIndexChanged(int index);
|
||||
void on_comboBoxFloppyType_activated(int index);
|
||||
void on_checkBoxCheckBPB_stateChanged(int arg1);
|
||||
void on_checkBoxTurboTimings_stateChanged(int arg1);
|
||||
void onFloppyRowChanged(const QModelIndex ¤t);
|
||||
void onCDROMRowChanged(const QModelIndex ¤t);
|
||||
|
||||
private:
|
||||
Ui::SettingsFloppyCDROM *ui;
|
||||
};
|
||||
|
||||
#endif // QT_SETTINGSFLOPPYCDROM_HPP
|
148
src/qt/qt_settingsfloppycdrom.ui
Normal file
148
src/qt/qt_settingsfloppycdrom.ui
Normal file
@ -0,0 +1,148 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SettingsFloppyCDROM</class>
|
||||
<widget class="QWidget" name="SettingsFloppyCDROM">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>544</width>
|
||||
<height>617</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Floppy Drives</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="tableViewFloppy">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxFloppyType"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxTurboTimings">
|
||||
<property name="text">
|
||||
<string>Turbo Timings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxCheckBPB">
|
||||
<property name="text">
|
||||
<string>Check BPB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>CD-ROM Drives</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="tableViewCDROM">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Channel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxBus"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Speed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Bus</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QComboBox" name="comboBoxChannel"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBoxSpeed"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
225
src/qt/qt_settingsharddisks.cpp
Normal file
225
src/qt/qt_settingsharddisks.cpp
Normal file
@ -0,0 +1,225 @@
|
||||
#include "qt_settingsharddisks.hpp"
|
||||
#include "ui_qt_settingsharddisks.h"
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/hdd.h>
|
||||
}
|
||||
|
||||
#include <QStandardItemModel>
|
||||
|
||||
#include "qt_harddiskdialog.hpp"
|
||||
#include "qt_harddrive_common.hpp"
|
||||
|
||||
const int ColumnBus = 0;
|
||||
const int ColumnFilename = 1;
|
||||
const int ColumnCylinders = 2;
|
||||
const int ColumnHeads = 3;
|
||||
const int ColumnSectors = 4;
|
||||
const int ColumnSize = 5;
|
||||
|
||||
const int DataBus = Qt::UserRole;
|
||||
const int DataBusChannel = Qt::UserRole + 1;
|
||||
|
||||
/*
|
||||
static void
|
||||
normalize_hd_list()
|
||||
{
|
||||
hard_disk_t ihdd[HDD_NUM];
|
||||
int i, j;
|
||||
|
||||
j = 0;
|
||||
memset(ihdd, 0x00, HDD_NUM * sizeof(hard_disk_t));
|
||||
|
||||
for (i = 0; i < HDD_NUM; i++) {
|
||||
if (temp_hdd[i].bus != HDD_BUS_DISABLED) {
|
||||
memcpy(&(ihdd[j]), &(temp_hdd[i]), sizeof(hard_disk_t));
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(temp_hdd, ihdd, HDD_NUM * sizeof(hard_disk_t));
|
||||
}
|
||||
*/
|
||||
|
||||
static QString busChannelName(const QModelIndex& idx) {
|
||||
return Harddrives::BusChannelName(idx.data(DataBus).toUInt(), idx.data(DataBusChannel).toUInt());
|
||||
}
|
||||
|
||||
static void addRow(QAbstractItemModel* model, hard_disk_t* hd) {
|
||||
const QString userPath = usr_path;
|
||||
|
||||
int row = model->rowCount();
|
||||
model->insertRow(row);
|
||||
|
||||
QString busName = Harddrives::BusChannelName(hd->bus, hd->channel);
|
||||
model->setData(model->index(row, ColumnBus), busName);
|
||||
model->setData(model->index(row, ColumnBus), QIcon(":/settings/win/icons/hard_disk.ico"), Qt::DecorationRole);
|
||||
model->setData(model->index(row, ColumnBus), hd->bus, DataBus);
|
||||
model->setData(model->index(row, ColumnBus), hd->channel, DataBusChannel);
|
||||
QString fileName = hd->fn;
|
||||
if (fileName.startsWith(userPath, Qt::CaseInsensitive)) {
|
||||
model->setData(model->index(row, ColumnFilename), fileName.mid(userPath.size()));
|
||||
} else {
|
||||
model->setData(model->index(row, ColumnFilename), fileName);
|
||||
}
|
||||
model->setData(model->index(row, ColumnFilename), fileName, Qt::UserRole);
|
||||
|
||||
model->setData(model->index(row, ColumnCylinders), hd->tracks);
|
||||
model->setData(model->index(row, ColumnHeads), hd->hpc);
|
||||
model->setData(model->index(row, ColumnSectors), hd->spt);
|
||||
model->setData(model->index(row, ColumnSize), (hd->tracks * hd->hpc * hd->spt) >> 11);
|
||||
}
|
||||
|
||||
SettingsHarddisks::SettingsHarddisks(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::SettingsHarddisks)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QAbstractItemModel* model = new QStandardItemModel(0, 6, this);
|
||||
model->setHeaderData(ColumnBus, Qt::Horizontal, "Bus");
|
||||
model->setHeaderData(ColumnFilename, Qt::Horizontal, "File");
|
||||
model->setHeaderData(ColumnCylinders, Qt::Horizontal, "C");
|
||||
model->setHeaderData(ColumnHeads, Qt::Horizontal, "H");
|
||||
model->setHeaderData(ColumnSectors, Qt::Horizontal, "S");
|
||||
model->setHeaderData(ColumnSize, Qt::Horizontal, "MiB");
|
||||
ui->tableView->setModel(model);
|
||||
|
||||
for (int i = 0; i < HDD_NUM; i++) {
|
||||
if (hdd[i].bus > 0) {
|
||||
addRow(model, &hdd[i]);
|
||||
}
|
||||
}
|
||||
ui->tableView->resizeColumnsToContents();
|
||||
ui->tableView->horizontalHeader()->setSectionResizeMode(ColumnFilename, QHeaderView::Stretch);
|
||||
|
||||
auto* tableSelectionModel = ui->tableView->selectionModel();
|
||||
connect(tableSelectionModel, &QItemSelectionModel::currentRowChanged, this, &SettingsHarddisks::onTableRowChanged);
|
||||
onTableRowChanged(QModelIndex());
|
||||
|
||||
Harddrives::populateBuses(ui->comboBoxBus->model());
|
||||
on_comboBoxBus_currentIndexChanged(0);
|
||||
}
|
||||
|
||||
SettingsHarddisks::~SettingsHarddisks()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SettingsHarddisks::save() {
|
||||
memset(hdd, 0, sizeof(hdd));
|
||||
|
||||
auto* model = ui->tableView->model();
|
||||
int rows = model->rowCount();
|
||||
for (int i = 0; i < rows; ++i) {
|
||||
auto idx = model->index(i, ColumnBus);
|
||||
hdd[i].bus = idx.data(DataBus).toUInt();
|
||||
hdd[i].channel = idx.data(DataBusChannel).toUInt();
|
||||
hdd[i].tracks = idx.siblingAtColumn(ColumnCylinders).data().toUInt();
|
||||
hdd[i].hpc = idx.siblingAtColumn(ColumnHeads).data().toUInt();
|
||||
hdd[i].spt = idx.siblingAtColumn(ColumnSectors).data().toUInt();
|
||||
|
||||
QByteArray fileName = idx.siblingAtColumn(ColumnFilename).data(Qt::UserRole).toString().toUtf8();
|
||||
strncpy(hdd[i].fn, fileName.data(), sizeof(hdd[i].fn));
|
||||
hdd[i].priv = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsHarddisks::on_comboBoxBus_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto idx = ui->tableView->selectionModel()->currentIndex();
|
||||
if (idx.isValid()) {
|
||||
auto* model = ui->tableView->model();
|
||||
auto col = idx.siblingAtColumn(ColumnBus);
|
||||
model->setData(col, ui->comboBoxBus->currentData(Qt::UserRole), DataBus);
|
||||
model->setData(col, busChannelName(col), Qt::DisplayRole);
|
||||
}
|
||||
|
||||
Harddrives::populateBusChannels(ui->comboBoxChannel->model(), ui->comboBoxBus->currentData().toInt());
|
||||
}
|
||||
|
||||
void SettingsHarddisks::on_comboBoxChannel_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto idx = ui->tableView->selectionModel()->currentIndex();
|
||||
if (idx.isValid()) {
|
||||
auto* model = ui->tableView->model();
|
||||
auto col = idx.siblingAtColumn(ColumnBus);
|
||||
model->setData(col, ui->comboBoxChannel->currentData(Qt::UserRole), DataBusChannel);
|
||||
model->setData(col, busChannelName(col), Qt::DisplayRole);
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsHarddisks::onTableRowChanged(const QModelIndex ¤t) {
|
||||
bool hidden = !current.isValid();
|
||||
ui->labelBus->setHidden(hidden);
|
||||
ui->labelChannel->setHidden(hidden);
|
||||
ui->comboBoxBus->setHidden(hidden);
|
||||
ui->comboBoxChannel->setHidden(hidden);
|
||||
|
||||
uint32_t bus = current.siblingAtColumn(ColumnBus).data(DataBus).toUInt();
|
||||
uint32_t busChannel = current.siblingAtColumn(ColumnBus).data(DataBusChannel).toUInt();
|
||||
|
||||
auto* model = ui->comboBoxBus->model();
|
||||
auto match = model->match(model->index(0, 0), Qt::UserRole, bus);
|
||||
if (! match.isEmpty()) {
|
||||
ui->comboBoxBus->setCurrentIndex(match.first().row());
|
||||
}
|
||||
model = ui->comboBoxChannel->model();
|
||||
match = model->match(model->index(0, 0), Qt::UserRole, busChannel);
|
||||
if (! match.isEmpty()) {
|
||||
ui->comboBoxChannel->setCurrentIndex(match.first().row());
|
||||
}
|
||||
}
|
||||
|
||||
static void addDriveFromDialog(Ui::SettingsHarddisks* ui, const HarddiskDialog& dlg) {
|
||||
QByteArray fn = dlg.fileName().toUtf8();
|
||||
|
||||
hard_disk_t hd;
|
||||
hd.bus = dlg.bus();
|
||||
hd.channel = dlg.channel();
|
||||
hd.tracks = dlg.cylinders();
|
||||
hd.hpc = dlg.heads();
|
||||
hd.spt = dlg.sectors();
|
||||
strncpy(hd.fn, fn.data(), sizeof(hd.fn));
|
||||
|
||||
addRow(ui->tableView->model(), &hd);
|
||||
ui->tableView->resizeColumnsToContents();
|
||||
ui->tableView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
|
||||
}
|
||||
|
||||
void SettingsHarddisks::on_pushButtonNew_clicked() {
|
||||
HarddiskDialog dialog(false, this);
|
||||
switch (dialog.exec()) {
|
||||
case QDialog::Accepted:
|
||||
addDriveFromDialog(ui, dialog);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SettingsHarddisks::on_pushButtonExisting_clicked() {
|
||||
HarddiskDialog dialog(true, this);
|
||||
switch (dialog.exec()) {
|
||||
case QDialog::Accepted:
|
||||
addDriveFromDialog(ui, dialog);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsHarddisks::on_pushButtonRemove_clicked() {
|
||||
auto idx = ui->tableView->selectionModel()->currentIndex();
|
||||
if (! idx.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* model = ui->tableView->model();
|
||||
model->removeRow(idx.row());
|
||||
}
|
||||
|
35
src/qt/qt_settingsharddisks.hpp
Normal file
35
src/qt/qt_settingsharddisks.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef QT_SETTINGSHARDDISKS_HPP
|
||||
#define QT_SETTINGSHARDDISKS_HPP
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class SettingsHarddisks;
|
||||
}
|
||||
|
||||
class SettingsHarddisks : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsHarddisks(QWidget *parent = nullptr);
|
||||
~SettingsHarddisks();
|
||||
|
||||
void save();
|
||||
|
||||
private slots:
|
||||
void on_comboBoxChannel_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void on_pushButtonRemove_clicked();
|
||||
void on_pushButtonExisting_clicked();
|
||||
void on_pushButtonNew_clicked();
|
||||
void on_comboBoxBus_currentIndexChanged(int index);
|
||||
|
||||
void onTableRowChanged(const QModelIndex& current);
|
||||
|
||||
private:
|
||||
Ui::SettingsHarddisks *ui;
|
||||
};
|
||||
|
||||
#endif // QT_SETTINGSHARDDISKS_HPP
|
95
src/qt/qt_settingsharddisks.ui
Normal file
95
src/qt/qt_settingsharddisks.ui
Normal file
@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SettingsHarddisks</class>
|
||||
<widget class="QWidget" name="SettingsHarddisks">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTableView" name="tableView">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelBus">
|
||||
<property name="text">
|
||||
<string>Bus</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxBus"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelChannel">
|
||||
<property name="text">
|
||||
<string>ID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxChannel"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonNew">
|
||||
<property name="text">
|
||||
<string>New</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonExisting">
|
||||
<property name="text">
|
||||
<string>Existing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonRemove">
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
114
src/qt/qt_settingsinput.cpp
Normal file
114
src/qt/qt_settingsinput.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
#include "qt_settingsinput.hpp"
|
||||
#include "ui_qt_settingsinput.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/mouse.h>
|
||||
#include <86box/gameport.h>
|
||||
}
|
||||
|
||||
#include "qt_deviceconfig.hpp"
|
||||
|
||||
SettingsInput::SettingsInput(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::SettingsInput)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
onCurrentMachineChanged(machine);
|
||||
}
|
||||
|
||||
SettingsInput::~SettingsInput()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SettingsInput::save() {
|
||||
mouse_type = ui->comboBoxMouse->currentData().toInt();
|
||||
joystick_type = ui->comboBoxJoystick->currentData().toInt();
|
||||
}
|
||||
|
||||
void SettingsInput::onCurrentMachineChanged(int machineId) {
|
||||
// win_settings_video_proc, WM_INITDIALOG
|
||||
this->machineId = machineId;
|
||||
|
||||
const auto* machine = &machines[machineId];
|
||||
auto* mouseModel = ui->comboBoxMouse->model();
|
||||
auto removeRows = mouseModel->rowCount();
|
||||
|
||||
int selectedRow = 0;
|
||||
for (int i = 0; i < mouse_get_ndev(); ++i) {
|
||||
const auto* dev = mouse_get_device(i);
|
||||
if ((i == MOUSE_TYPE_INTERNAL) && !(machines[machineId].flags & MACHINE_MOUSE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (device_is_valid(dev, machine->flags) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString name = DeviceConfig::DeviceName(dev, mouse_get_internal_name(i), 0);
|
||||
int row = mouseModel->rowCount();
|
||||
mouseModel->insertRow(row);
|
||||
auto idx = mouseModel->index(row, 0);
|
||||
|
||||
mouseModel->setData(idx, name, Qt::DisplayRole);
|
||||
mouseModel->setData(idx, i, Qt::UserRole);
|
||||
|
||||
if (i == mouse_type) {
|
||||
selectedRow = row - removeRows;
|
||||
}
|
||||
}
|
||||
mouseModel->removeRows(0, removeRows);
|
||||
ui->comboBoxMouse->setCurrentIndex(selectedRow);
|
||||
|
||||
|
||||
int i = 0;
|
||||
char* joyName = joystick_get_name(i);
|
||||
auto* joystickModel = ui->comboBoxJoystick->model();
|
||||
removeRows = joystickModel->rowCount();
|
||||
selectedRow = 0;
|
||||
while (joyName) {
|
||||
int row = joystickModel->rowCount();
|
||||
joystickModel->insertRow(row);
|
||||
auto idx = joystickModel->index(row, 0);
|
||||
|
||||
joystickModel->setData(idx, joyName, Qt::DisplayRole);
|
||||
joystickModel->setData(idx, i, Qt::UserRole);
|
||||
|
||||
if (i == joystick_type) {
|
||||
selectedRow = row - removeRows;
|
||||
}
|
||||
|
||||
++i;
|
||||
joyName = joystick_get_name(i);
|
||||
}
|
||||
joystickModel->removeRows(0, removeRows);
|
||||
ui->comboBoxJoystick->setCurrentIndex(selectedRow);
|
||||
}
|
||||
|
||||
void SettingsInput::on_comboBoxMouse_currentIndexChanged(int index) {
|
||||
int mouseId = ui->comboBoxMouse->currentData().toInt();
|
||||
ui->pushButtonConfigureMouse->setEnabled(mouse_has_config(mouseId) > 0);
|
||||
}
|
||||
|
||||
|
||||
void SettingsInput::on_comboBoxJoystick_currentIndexChanged(int index) {
|
||||
int joystickId = ui->comboBoxJoystick->currentData().toInt();
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
auto* btn = findChild<QPushButton*>(QString("pushButtonJoystick%1").arg(i+1));
|
||||
if (btn == nullptr) {
|
||||
continue;
|
||||
}
|
||||
btn->setEnabled(joystick_get_max_joysticks(joystickId) > i);
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsInput::on_pushButtonConfigureMouse_clicked() {
|
||||
int mouseId = ui->comboBoxMouse->currentData().toInt();
|
||||
DeviceConfig::ConfigureDevice(mouse_get_device(mouseId));
|
||||
}
|
33
src/qt/qt_settingsinput.hpp
Normal file
33
src/qt/qt_settingsinput.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef QT_SETTINGSINPUT_HPP
|
||||
#define QT_SETTINGSINPUT_HPP
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class SettingsInput;
|
||||
}
|
||||
|
||||
class SettingsInput : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsInput(QWidget *parent = nullptr);
|
||||
~SettingsInput();
|
||||
|
||||
void save();
|
||||
|
||||
public slots:
|
||||
void onCurrentMachineChanged(int machineId);
|
||||
|
||||
private slots:
|
||||
void on_pushButtonConfigureMouse_clicked();
|
||||
void on_comboBoxJoystick_currentIndexChanged(int index);
|
||||
void on_comboBoxMouse_currentIndexChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::SettingsInput *ui;
|
||||
int machineId = 0;
|
||||
};
|
||||
|
||||
#endif // QT_SETTINGSINPUT_HPP
|
134
src/qt/qt_settingsinput.ui
Normal file
134
src/qt/qt_settingsinput.ui
Normal file
@ -0,0 +1,134 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SettingsInput</class>
|
||||
<widget class="QWidget" name="SettingsInput">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Mouse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxMouse"/>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigureMouse">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Joystick</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBoxJoystick"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonJoystick1">
|
||||
<property name="text">
|
||||
<string>Joystick 1...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonJoystick2">
|
||||
<property name="text">
|
||||
<string>Joystick 2...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonJoystick3">
|
||||
<property name="text">
|
||||
<string>Joystick 3...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonJoystick4">
|
||||
<property name="text">
|
||||
<string>Joystick 4...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
348
src/qt/qt_settingsmachine.cpp
Normal file
348
src/qt/qt_settingsmachine.cpp
Normal file
@ -0,0 +1,348 @@
|
||||
#include "qt_settingsmachine.hpp"
|
||||
#include "ui_qt_settingsmachine.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDialog>
|
||||
#include <QFrame>
|
||||
#include <QVBoxLayout>
|
||||
#include <QDialogButtonBox>
|
||||
|
||||
extern "C" {
|
||||
#include "../cpu/cpu.h"
|
||||
|
||||
#include <86box/86box.h>
|
||||
#include <86box/config.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/machine.h>
|
||||
}
|
||||
|
||||
// from nvr.h, which we can't import into CPP code
|
||||
#define TIME_SYNC_DISABLED 0
|
||||
#define TIME_SYNC_ENABLED 1
|
||||
#define TIME_SYNC_UTC 2
|
||||
|
||||
#include "qt_deviceconfig.hpp"
|
||||
#include "qt_models_common.hpp"
|
||||
|
||||
/*
|
||||
class MachineModel : public QAbstractListModel {
|
||||
public:
|
||||
MachineModel(QObject* parent) : QAbstractListModel(parent) {}
|
||||
|
||||
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
private:
|
||||
struct Entry {
|
||||
QString name;
|
||||
int id;
|
||||
};
|
||||
QList<Entry> entries;
|
||||
};
|
||||
|
||||
bool MachineModel::insertRows(int row, int count, const QModelIndex &parent) {
|
||||
beginInsertRows(parent, row, row + count - 1);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
entries.insert(row, Entry{});
|
||||
}
|
||||
endInsertRows();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MachineModel::removeRows(int row, int count, const QModelIndex &parent) {
|
||||
beginRemoveRows(parent, row, row + count - 1);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
entries.removeAt(row);
|
||||
}
|
||||
endRemoveRows();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant MachineModel::data(const QModelIndex &index, int role) const {
|
||||
Q_ASSERT(checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::ParentIsInvalid));
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return entries.at(index.row()).name;
|
||||
case Qt::UserRole:
|
||||
return entries.at(index.row()).id;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
int MachineModel::rowCount(const QModelIndex &parent) const {
|
||||
(void) parent;
|
||||
return entries.size();
|
||||
}
|
||||
|
||||
bool MachineModel::setData(const QModelIndex &index, const QVariant &value, int role) {
|
||||
Entry* entry = nullptr;
|
||||
if (index.row() < entries.size()) {
|
||||
entry = &entries[index.row()];
|
||||
} else if (index.row() == entries.size()) {
|
||||
entries.append(Entry{});
|
||||
entry = &entries.back();
|
||||
}
|
||||
|
||||
bool ret = true;
|
||||
if (entry != nullptr) {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
entry->name = value.toString();
|
||||
case Qt::UserRole:
|
||||
entry->id = value.toInt();
|
||||
default:
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
|
||||
SettingsMachine::SettingsMachine(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::SettingsMachine)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
switch (time_sync) {
|
||||
case TIME_SYNC_ENABLED:
|
||||
ui->radioButtonLocalTime->setChecked(true);
|
||||
break;
|
||||
case TIME_SYNC_ENABLED | TIME_SYNC_UTC:
|
||||
ui->radioButtonUTC->setChecked(true);
|
||||
break;
|
||||
case TIME_SYNC_DISABLED:
|
||||
default:
|
||||
ui->radioButtonDisabled->setChecked(true);
|
||||
break;
|
||||
}
|
||||
|
||||
auto* waitStatesModel = ui->comboBoxWaitStates->model();
|
||||
waitStatesModel->insertRows(0, 9);
|
||||
auto idx = waitStatesModel->index(0, 0);
|
||||
waitStatesModel->setData(idx, "Default", Qt::DisplayRole);
|
||||
waitStatesModel->setData(idx, 0, Qt::UserRole);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
idx = waitStatesModel->index(i+1, 0);
|
||||
waitStatesModel->setData(idx, QString("%1 Wait State(s)").arg(i), Qt::DisplayRole);
|
||||
waitStatesModel->setData(idx, i+1, Qt::UserRole);
|
||||
}
|
||||
|
||||
int selectedMachineType = 0;
|
||||
auto* machineTypesModel = ui->comboBoxMachineType->model();
|
||||
for (int i = 0; i < MACHINE_TYPE_MAX; ++i) {
|
||||
Models::AddEntry(machineTypesModel, machine_types[i].name, machine_types[i].id);
|
||||
if (machine_types[i].id == machines[machine].type) {
|
||||
selectedMachineType = i;
|
||||
}
|
||||
}
|
||||
ui->comboBoxMachineType->setCurrentIndex(selectedMachineType);
|
||||
}
|
||||
|
||||
SettingsMachine::~SettingsMachine() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SettingsMachine::save() {
|
||||
machine = ui->comboBoxMachine->currentData().toInt();
|
||||
cpu_f = const_cast<cpu_family_t*>(&cpu_families[ui->comboBoxCPU->currentData().toInt()]);
|
||||
cpu = ui->comboBoxSpeed->currentData().toInt();
|
||||
fpu_type = ui->comboBoxFPU->currentData().toInt();
|
||||
cpu_use_dynarec = ui->checkBoxDynamicRecompiler->isChecked() ? 1 : 0;
|
||||
if (machines[machine].ram_granularity < 1024) {
|
||||
mem_size = ui->spinBoxRAM->value();
|
||||
} else {
|
||||
mem_size = ui->spinBoxRAM->value() * 1024;
|
||||
}
|
||||
if (ui->comboBoxWaitStates->isEnabled()) {
|
||||
cpu_waitstates = ui->comboBoxWaitStates->currentData().toInt();
|
||||
} else {
|
||||
cpu_waitstates = 0;
|
||||
}
|
||||
|
||||
time_sync = 0;
|
||||
if (ui->radioButtonLocalTime->isChecked()) {
|
||||
time_sync = TIME_SYNC_ENABLED;
|
||||
}
|
||||
if (ui->radioButtonUTC->isChecked()) {
|
||||
time_sync = TIME_SYNC_ENABLED | TIME_SYNC_UTC;
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsMachine::on_comboBoxMachineType_currentIndexChanged(int index) {
|
||||
auto* model = ui->comboBoxMachine->model();
|
||||
int removeRows = model->rowCount();
|
||||
|
||||
int selectedMachineRow = 0;
|
||||
for (int i = 0; i < machine_count(); ++i) {
|
||||
if ((machines[i].type == index) && machine_available(i)) {
|
||||
int row = Models::AddEntry(model, machines[i].name, i);
|
||||
if (i == machine) {
|
||||
selectedMachineRow = row - removeRows;
|
||||
}
|
||||
}
|
||||
}
|
||||
model->removeRows(0, removeRows);
|
||||
|
||||
ui->comboBoxMachine->setCurrentIndex(-1);
|
||||
ui->comboBoxMachine->setCurrentIndex(selectedMachineRow);
|
||||
}
|
||||
|
||||
|
||||
void SettingsMachine::on_comboBoxMachine_currentIndexChanged(int index) {
|
||||
// win_settings_machine_recalc_machine
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int machineId = ui->comboBoxMachine->currentData().toInt();
|
||||
const auto* device = machine_getdevice(machineId);
|
||||
ui->pushButtonConfigure->setEnabled((device != nullptr) && (device->config != nullptr));
|
||||
|
||||
auto* modelCpu = ui->comboBoxCPU->model();
|
||||
int removeRows = modelCpu->rowCount();
|
||||
|
||||
int i = 0;
|
||||
int eligibleRows = 0;
|
||||
int selectedCpuFamilyRow = 0;
|
||||
while (cpu_families[i].package != 0) {
|
||||
if (cpu_family_is_eligible(&cpu_families[i], machineId)) {
|
||||
Models::AddEntry(modelCpu, QString("%1 %2").arg(cpu_families[i].manufacturer, cpu_families[i].name), i);
|
||||
if (&cpu_families[i] == cpu_f) {
|
||||
selectedCpuFamilyRow = eligibleRows;
|
||||
}
|
||||
++eligibleRows;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
modelCpu->removeRows(0, removeRows);
|
||||
ui->comboBoxCPU->setEnabled(eligibleRows > 1);
|
||||
ui->comboBoxCPU->setCurrentIndex(-1);
|
||||
ui->comboBoxCPU->setCurrentIndex(selectedCpuFamilyRow);
|
||||
|
||||
auto* machine = &machines[machineId];
|
||||
if ((machine->ram_granularity < 1024)) {
|
||||
ui->spinBoxRAM->setMinimum(machine->min_ram);
|
||||
ui->spinBoxRAM->setMaximum(machine->max_ram);
|
||||
ui->spinBoxRAM->setSingleStep(machine->ram_granularity);
|
||||
ui->spinBoxRAM->setSuffix(" KiB");
|
||||
ui->spinBoxRAM->setValue(mem_size);
|
||||
} else {
|
||||
uint maxram;
|
||||
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
|
||||
maxram = std::min(machine->max_ram, 2097152U);
|
||||
#else
|
||||
maxram = std::min(machine->max_ram, 3145728U);
|
||||
#endif
|
||||
ui->spinBoxRAM->setMinimum(machine->min_ram / 1024);
|
||||
ui->spinBoxRAM->setMaximum(maxram / 1024);
|
||||
ui->spinBoxRAM->setSingleStep(machine->ram_granularity / 1024);
|
||||
ui->spinBoxRAM->setSuffix(" MiB");
|
||||
ui->spinBoxRAM->setValue(mem_size / 1024);
|
||||
}
|
||||
ui->spinBoxRAM->setEnabled(machine->min_ram != machine->max_ram);
|
||||
ui->spinBoxRAM->setEnabled(machine->min_ram != machine->max_ram);
|
||||
|
||||
emit currentMachineChanged(machineId);
|
||||
}
|
||||
|
||||
|
||||
void SettingsMachine::on_comboBoxCPU_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int machineId = ui->comboBoxMachine->currentData().toInt();
|
||||
int cpuFamilyId = ui->comboBoxCPU->currentData().toInt();
|
||||
const auto* cpuFamily = &cpu_families[cpuFamilyId];
|
||||
|
||||
auto* modelSpeed = ui->comboBoxSpeed->model();
|
||||
int removeRows = modelSpeed->rowCount();
|
||||
|
||||
// win_settings_machine_recalc_cpu_m
|
||||
int i = 0;
|
||||
int eligibleRows = 0;
|
||||
int selectedSpeedRow = 0;
|
||||
while (cpuFamily->cpus[i].cpu_type != 0) {
|
||||
if (cpu_is_eligible(cpuFamily, i, machineId)) {
|
||||
Models::AddEntry(modelSpeed, QString("%1").arg(cpuFamily->cpus[i].name), i);
|
||||
if (cpu == i) {
|
||||
selectedSpeedRow = eligibleRows;
|
||||
}
|
||||
++eligibleRows;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
modelSpeed->removeRows(0, removeRows);
|
||||
ui->comboBoxSpeed->setEnabled(eligibleRows > 1);
|
||||
ui->comboBoxSpeed->setCurrentIndex(-1);
|
||||
ui->comboBoxSpeed->setCurrentIndex(selectedSpeedRow);
|
||||
}
|
||||
|
||||
|
||||
void SettingsMachine::on_comboBoxSpeed_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// win_settings_machine_recalc_cpu
|
||||
int cpuFamilyId = ui->comboBoxCPU->currentData().toInt();
|
||||
const auto* cpuFamily = &cpu_families[cpuFamilyId];
|
||||
int cpuId = ui->comboBoxSpeed->currentData().toInt();
|
||||
uint cpuType = cpuFamily->cpus[cpuId].cpu_type;
|
||||
|
||||
if ((cpuType >= CPU_286) && (cpuType <= CPU_386DX)) {
|
||||
ui->comboBoxWaitStates->setEnabled(true);
|
||||
ui->comboBoxWaitStates->setCurrentIndex(cpu_waitstates);
|
||||
} else {
|
||||
ui->comboBoxWaitStates->setCurrentIndex(0);
|
||||
ui->comboBoxWaitStates->setEnabled(false);
|
||||
}
|
||||
|
||||
#ifdef USE_DYNAREC
|
||||
uint8_t flags = cpuFamily->cpus[cpuId].cpu_flags;
|
||||
if (! (flags & CPU_SUPPORTS_DYNAREC)) {
|
||||
ui->checkBoxDynamicRecompiler->setChecked(false);
|
||||
ui->checkBoxDynamicRecompiler->setEnabled(false);
|
||||
} else if (flags & CPU_REQUIRES_DYNAREC) {
|
||||
ui->checkBoxDynamicRecompiler->setChecked(true);
|
||||
ui->checkBoxDynamicRecompiler->setEnabled(false);
|
||||
} else {
|
||||
ui->checkBoxDynamicRecompiler->setChecked(cpu_use_dynarec);
|
||||
ui->checkBoxDynamicRecompiler->setEnabled(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
// win_settings_machine_recalc_fpu
|
||||
auto* modelFpu = ui->comboBoxFPU->model();
|
||||
int removeRows = modelFpu->rowCount();
|
||||
|
||||
int i = 0;
|
||||
int selectedFpuRow = 0;
|
||||
for (const char* fpuName = fpu_get_name_from_index(cpuFamily, cpuId, i); fpuName != nullptr; fpuName = fpu_get_name_from_index(cpuFamily, cpuId, ++i)) {
|
||||
auto fpuType = fpu_get_type_from_index(cpuFamily, cpuId, i);
|
||||
Models::AddEntry(modelFpu, QString("%1").arg(fpuName), fpuType);
|
||||
if (fpu_type == fpuType) {
|
||||
selectedFpuRow = i;
|
||||
}
|
||||
}
|
||||
|
||||
modelFpu->removeRows(0, removeRows);
|
||||
ui->comboBoxFPU->setEnabled(modelFpu->rowCount() > 1);
|
||||
ui->comboBoxFPU->setCurrentIndex(-1);
|
||||
ui->comboBoxFPU->setCurrentIndex(selectedFpuRow);
|
||||
}
|
||||
|
||||
void SettingsMachine::on_pushButtonConfigure_clicked() {
|
||||
// deviceconfig_inst_open
|
||||
int machineId = ui->comboBoxMachine->currentData().toInt();
|
||||
const auto* device = machine_getdevice(machineId);
|
||||
DeviceConfig::ConfigureDevice(device);
|
||||
}
|
41
src/qt/qt_settingsmachine.hpp
Normal file
41
src/qt/qt_settingsmachine.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef QT_SETTINGSMACHINE_HPP
|
||||
#define QT_SETTINGSMACHINE_HPP
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class SettingsMachine;
|
||||
}
|
||||
|
||||
class SettingsMachine : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsMachine(QWidget *parent = nullptr);
|
||||
~SettingsMachine();
|
||||
|
||||
void save();
|
||||
|
||||
signals:
|
||||
void currentMachineChanged(int machineId);
|
||||
private slots:
|
||||
void on_pushButtonConfigure_clicked();
|
||||
|
||||
private slots:
|
||||
void on_comboBoxSpeed_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxCPU_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxMachine_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxMachineType_currentIndexChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::SettingsMachine *ui;
|
||||
};
|
||||
|
||||
#endif // QT_SETTINGSMACHINE_HPP
|
229
src/qt/qt_settingsmachine.ui
Normal file
229
src/qt/qt_settingsmachine.ui
Normal file
@ -0,0 +1,229 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SettingsMachine</class>
|
||||
<widget class="QWidget" name="SettingsMachine">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>458</width>
|
||||
<height>390</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Machine Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxMachineType"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Machine</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>CPU</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>FPU</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Wait States</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Memory</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="comboBoxFPU"/>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="comboBoxWaitStates"/>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxRAM"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxCPU"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Speed</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxSpeed"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QWidget" name="widget_3" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxMachine"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonConfigure">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxDynamicRecompiler">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>2</horstretch>
|
||||
<verstretch>2</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Dynamic Recompiler</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Time Synchronization</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonDisabled">
|
||||
<property name="text">
|
||||
<string>Disabled</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonLocalTime">
|
||||
<property name="text">
|
||||
<string>Enabled (Local Time)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButtonUTC">
|
||||
<property name="text">
|
||||
<string>Enabled (UTC)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
113
src/qt/qt_settingsnetwork.cpp
Normal file
113
src/qt/qt_settingsnetwork.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
#include "qt_settingsnetwork.hpp"
|
||||
#include "ui_qt_settingsnetwork.h"
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/network.h>
|
||||
}
|
||||
|
||||
#include "qt_models_common.hpp"
|
||||
#include "qt_deviceconfig.hpp"
|
||||
|
||||
static void enableElements(Ui::SettingsNetwork *ui) {
|
||||
int netType = ui->comboBoxNetwork->currentData().toInt();
|
||||
ui->comboBoxPcap->setEnabled(netType == NET_TYPE_PCAP);
|
||||
|
||||
bool adaptersEnabled = netType == NET_TYPE_SLIRP ||
|
||||
(netType == NET_TYPE_PCAP && ui->comboBoxPcap->currentData().toInt() > 0);
|
||||
ui->comboBoxAdapter->setEnabled(adaptersEnabled);
|
||||
ui->pushButtonConfigure->setEnabled(adaptersEnabled && ui->comboBoxAdapter->currentIndex() > 0);
|
||||
}
|
||||
|
||||
SettingsNetwork::SettingsNetwork(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::SettingsNetwork)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
auto* model = ui->comboBoxNetwork->model();
|
||||
Models::AddEntry(model, "None", NET_TYPE_NONE);
|
||||
Models::AddEntry(model, "PCap", NET_TYPE_PCAP);
|
||||
Models::AddEntry(model, "SLiRP", NET_TYPE_SLIRP);
|
||||
ui->comboBoxNetwork->setCurrentIndex(network_type);
|
||||
|
||||
int selectedRow = 0;
|
||||
model = ui->comboBoxPcap->model();
|
||||
QString currentPcapDevice = network_host;
|
||||
for (int c = 0; c < network_ndev; c++) {
|
||||
|
||||
Models::AddEntry(model, network_devs[c].description, c);
|
||||
if (QString(network_devs[c].device) == currentPcapDevice) {
|
||||
selectedRow = c;
|
||||
}
|
||||
}
|
||||
ui->comboBoxPcap->setCurrentIndex(-1);
|
||||
ui->comboBoxPcap->setCurrentIndex(selectedRow);
|
||||
|
||||
onCurrentMachineChanged(machine);
|
||||
enableElements(ui);
|
||||
}
|
||||
|
||||
SettingsNetwork::~SettingsNetwork()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SettingsNetwork::save() {
|
||||
network_type = ui->comboBoxNetwork->currentData().toInt();
|
||||
memset(network_host, '\0', sizeof(network_host));
|
||||
strcpy(network_host, network_devs[ui->comboBoxPcap->currentData().toInt()].device);
|
||||
network_card = ui->comboBoxAdapter->currentData().toInt();
|
||||
}
|
||||
|
||||
void SettingsNetwork::onCurrentMachineChanged(int machineId) {
|
||||
this->machineId = machineId;
|
||||
auto* machine = &machines[machineId];
|
||||
|
||||
auto* model = ui->comboBoxAdapter->model();
|
||||
auto removeRows = model->rowCount();
|
||||
int c = 0;
|
||||
int selectedRow = 0;
|
||||
while (true) {
|
||||
auto name = DeviceConfig::DeviceName(network_card_getdevice(c), network_card_get_internal_name(c), 1);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (network_card_available(c) && device_is_valid(network_card_getdevice(c), machine->flags)) {
|
||||
int row = Models::AddEntry(model, name, c);
|
||||
if (c == network_card) {
|
||||
selectedRow = row - removeRows;
|
||||
}
|
||||
}
|
||||
|
||||
c++;
|
||||
}
|
||||
model->removeRows(0, removeRows);
|
||||
ui->comboBoxAdapter->setEnabled(model->rowCount() > 0);
|
||||
ui->comboBoxAdapter->setCurrentIndex(-1);
|
||||
ui->comboBoxAdapter->setCurrentIndex(selectedRow);
|
||||
}
|
||||
|
||||
void SettingsNetwork::on_comboBoxNetwork_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
enableElements(ui);
|
||||
}
|
||||
|
||||
void SettingsNetwork::on_comboBoxAdapter_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
enableElements(ui);
|
||||
}
|
||||
|
||||
void SettingsNetwork::on_pushButtonConfigure_clicked() {
|
||||
DeviceConfig::ConfigureDevice(network_card_getdevice(ui->comboBoxAdapter->currentData().toInt()));
|
||||
}
|
||||
|
33
src/qt/qt_settingsnetwork.hpp
Normal file
33
src/qt/qt_settingsnetwork.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef QT_SETTINGSNETWORK_HPP
|
||||
#define QT_SETTINGSNETWORK_HPP
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class SettingsNetwork;
|
||||
}
|
||||
|
||||
class SettingsNetwork : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsNetwork(QWidget *parent = nullptr);
|
||||
~SettingsNetwork();
|
||||
|
||||
void save();
|
||||
|
||||
public slots:
|
||||
void onCurrentMachineChanged(int machineId);
|
||||
|
||||
private slots:
|
||||
void on_pushButtonConfigure_clicked();
|
||||
void on_comboBoxAdapter_currentIndexChanged(int index);
|
||||
void on_comboBoxNetwork_currentIndexChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::SettingsNetwork *ui;
|
||||
int machineId = 0;
|
||||
};
|
||||
|
||||
#endif // QT_SETTINGSNETWORK_HPP
|
101
src/qt/qt_settingsnetwork.ui
Normal file
101
src/qt/qt_settingsnetwork.ui
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SettingsNetwork</class>
|
||||
<widget class="QWidget" name="SettingsNetwork">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>PCap Device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Network Adapter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBoxPcap"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxNetwork"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Network Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxAdapter"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonConfigure">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
133
src/qt/qt_settingsotherperipherals.cpp
Normal file
133
src/qt/qt_settingsotherperipherals.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
#include "qt_settingsotherperipherals.hpp"
|
||||
#include "ui_qt_settingsotherperipherals.h"
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/isamem.h>
|
||||
#include <86box/isartc.h>
|
||||
}
|
||||
|
||||
#include "qt_deviceconfig.hpp"
|
||||
#include "qt_models_common.hpp"
|
||||
|
||||
SettingsOtherPeripherals::SettingsOtherPeripherals(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::SettingsOtherPeripherals)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->checkBoxISABugger->setChecked(bugger_enabled > 0 ? true : false);
|
||||
ui->checkBoxPOSTCard->setChecked(postcard_enabled > 0 ? true : false);
|
||||
|
||||
auto* model = ui->comboBoxRTC->model();
|
||||
int d = 0;
|
||||
int selectedRow = 0;
|
||||
while (true) {
|
||||
QString name = DeviceConfig::DeviceName(isartc_get_device(d), isartc_get_internal_name(d), 0);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
int row = Models::AddEntry(model, name, d);
|
||||
if (d == isartc_type) {
|
||||
selectedRow = row;
|
||||
}
|
||||
++d;
|
||||
}
|
||||
ui->comboBoxRTC->setCurrentIndex(selectedRow);
|
||||
|
||||
for (int c = 0; c < ISAMEM_MAX; c++) {
|
||||
auto* cbox = findChild<QComboBox*>(QString("comboBoxCard%1").arg(c + 1));
|
||||
model = cbox->model();
|
||||
d = 0;
|
||||
selectedRow = 0;
|
||||
while (true) {
|
||||
QString name = DeviceConfig::DeviceName(isamem_get_device(d), isamem_get_internal_name(d), 0);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
int row = Models::AddEntry(model, name, d);
|
||||
if (d == isartc_type) {
|
||||
selectedRow = row;
|
||||
}
|
||||
++d;
|
||||
}
|
||||
cbox->setCurrentIndex(-1);
|
||||
cbox->setCurrentIndex(selectedRow);
|
||||
}
|
||||
}
|
||||
|
||||
SettingsOtherPeripherals::~SettingsOtherPeripherals()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SettingsOtherPeripherals::save() {
|
||||
/* Other peripherals category */
|
||||
bugger_enabled = ui->checkBoxISABugger->isChecked() ? 1 : 0;
|
||||
postcard_enabled = ui->checkBoxPOSTCard->isChecked() ? 1 : 0;
|
||||
isartc_type = ui->comboBoxRTC->currentData().toInt();
|
||||
|
||||
/* ISA memory boards. */
|
||||
for (int i = 0; i < ISAMEM_MAX; i++) {
|
||||
auto* cbox = findChild<QComboBox*>(QString("comboBoxCard%1").arg(i + 1));
|
||||
isamem_type[i] = cbox->currentData().toInt();
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsOtherPeripherals::on_comboBoxRTC_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
ui->pushButtonConfigureRTC->setEnabled(index != 0);
|
||||
}
|
||||
|
||||
void SettingsOtherPeripherals::on_pushButtonConfigureRTC_clicked() {
|
||||
DeviceConfig::ConfigureDevice(isartc_get_device(ui->comboBoxRTC->currentData().toInt()));
|
||||
}
|
||||
|
||||
void SettingsOtherPeripherals::on_comboBoxCard1_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
ui->pushButtonConfigureCard1->setEnabled(index != 0);
|
||||
}
|
||||
|
||||
void SettingsOtherPeripherals::on_pushButtonConfigureCard1_clicked() {
|
||||
DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard1->currentData().toInt()));
|
||||
}
|
||||
|
||||
void SettingsOtherPeripherals::on_comboBoxCard2_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
ui->pushButtonConfigureCard2->setEnabled(index != 0);
|
||||
}
|
||||
|
||||
void SettingsOtherPeripherals::on_pushButtonConfigureCard2_clicked() {
|
||||
DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard2->currentData().toInt()));
|
||||
}
|
||||
|
||||
void SettingsOtherPeripherals::on_comboBoxCard3_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
ui->pushButtonConfigureCard3->setEnabled(index != 0);
|
||||
}
|
||||
|
||||
void SettingsOtherPeripherals::on_pushButtonConfigureCard3_clicked() {
|
||||
DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard3->currentData().toInt()));
|
||||
}
|
||||
|
||||
void SettingsOtherPeripherals::on_comboBoxCard4_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
ui->pushButtonConfigureCard4->setEnabled(index != 0);
|
||||
}
|
||||
|
||||
void SettingsOtherPeripherals::on_pushButtonConfigureCard4_clicked() {
|
||||
DeviceConfig::ConfigureDevice(isamem_get_device(ui->comboBoxCard4->currentData().toInt()));
|
||||
}
|
53
src/qt/qt_settingsotherperipherals.hpp
Normal file
53
src/qt/qt_settingsotherperipherals.hpp
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef QT_SETTINGSOTHERPERIPHERALS_HPP
|
||||
#define QT_SETTINGSOTHERPERIPHERALS_HPP
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class SettingsOtherPeripherals;
|
||||
}
|
||||
|
||||
class SettingsOtherPeripherals : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsOtherPeripherals(QWidget *parent = nullptr);
|
||||
~SettingsOtherPeripherals();
|
||||
|
||||
void save();
|
||||
private slots:
|
||||
void on_pushButtonConfigureCard4_clicked();
|
||||
|
||||
private slots:
|
||||
void on_comboBoxCard4_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void on_pushButtonConfigureCard3_clicked();
|
||||
|
||||
private slots:
|
||||
void on_comboBoxCard3_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void on_pushButtonConfigureCard2_clicked();
|
||||
|
||||
private slots:
|
||||
void on_comboBoxCard2_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void on_pushButtonConfigureCard1_clicked();
|
||||
|
||||
private slots:
|
||||
void on_comboBoxCard1_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void on_pushButtonConfigureRTC_clicked();
|
||||
|
||||
private slots:
|
||||
void on_comboBoxRTC_currentIndexChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::SettingsOtherPeripherals *ui;
|
||||
};
|
||||
|
||||
#endif // QT_SETTINGSOTHERPERIPHERALS_HPP
|
162
src/qt/qt_settingsotherperipherals.ui
Normal file
162
src/qt/qt_settingsotherperipherals.ui
Normal file
@ -0,0 +1,162 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SettingsOtherPeripherals</class>
|
||||
<widget class="QWidget" name="SettingsOtherPeripherals">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>421</width>
|
||||
<height>458</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>ISA RTC</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxRTC"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonConfigureRTC">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>ISA Memory Expansion</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigureCard2">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBoxCard2"/>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigureCard3">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Card 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Card 3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigureCard1">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxCard1"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Card 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboBoxCard3"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboBoxCard4"/>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="pushButtonConfigureCard4">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Card 4</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxISABugger">
|
||||
<property name="text">
|
||||
<string>ISABugger Device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxPOSTCard">
|
||||
<property name="text">
|
||||
<string>POST card</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
267
src/qt/qt_settingsotherremovable.cpp
Normal file
267
src/qt/qt_settingsotherremovable.cpp
Normal file
@ -0,0 +1,267 @@
|
||||
#include "qt_settingsotherremovable.hpp"
|
||||
#include "ui_qt_settingsotherremovable.h"
|
||||
|
||||
extern "C" {
|
||||
#include <86box/timer.h>
|
||||
#include <86box/scsi_device.h>
|
||||
#include <86box/mo.h>
|
||||
#include <86box/zip.h>
|
||||
}
|
||||
|
||||
#include <QStandardItemModel>
|
||||
|
||||
#include "qt_models_common.hpp"
|
||||
#include "qt_harddrive_common.hpp"
|
||||
|
||||
static QString moDriveTypeName(int i) {
|
||||
return QString("%1 %2 %3").arg(mo_drive_types[i].vendor, mo_drive_types[i].model, mo_drive_types[i].revision);
|
||||
}
|
||||
|
||||
static void setMOBus(QAbstractItemModel* model, const QModelIndex& idx, uint8_t bus, uint8_t channel) {
|
||||
QIcon icon;
|
||||
switch (bus) {
|
||||
case MO_BUS_DISABLED:
|
||||
icon = QIcon(":/settings/win/icons/mo_disabled.ico");
|
||||
break;
|
||||
case MO_BUS_ATAPI:
|
||||
case MO_BUS_SCSI:
|
||||
icon = QIcon(":/settings/win/icons/mo.ico");
|
||||
break;
|
||||
}
|
||||
|
||||
auto i = idx.siblingAtColumn(0);
|
||||
model->setData(i, Harddrives::BusChannelName(bus, channel));
|
||||
model->setData(i, bus, Qt::UserRole);
|
||||
model->setData(i, channel, Qt::UserRole + 1);
|
||||
model->setData(i, icon, Qt::DecorationRole);
|
||||
}
|
||||
|
||||
static void setMOType(QAbstractItemModel* model, const QModelIndex& idx, uint32_t type) {
|
||||
auto i = idx.siblingAtColumn(1);
|
||||
if (idx.siblingAtColumn(0).data(Qt::UserRole).toUInt() == MO_BUS_DISABLED) {
|
||||
model->setData(i, "None");
|
||||
} else {
|
||||
model->setData(i, moDriveTypeName(type));
|
||||
}
|
||||
model->setData(i, type, Qt::UserRole);
|
||||
}
|
||||
|
||||
static void setZIPBus(QAbstractItemModel* model, const QModelIndex& idx, uint8_t bus, uint8_t channel) {
|
||||
QIcon icon;
|
||||
switch (bus) {
|
||||
case ZIP_BUS_DISABLED:
|
||||
icon = QIcon(":/settings/win/icons/zip_disabled.ico");
|
||||
break;
|
||||
case ZIP_BUS_ATAPI:
|
||||
case ZIP_BUS_SCSI:
|
||||
icon = QIcon(":/settings/win/icons/zip.ico");
|
||||
break;
|
||||
}
|
||||
|
||||
auto i = idx.siblingAtColumn(0);
|
||||
model->setData(i, Harddrives::BusChannelName(bus, channel));
|
||||
model->setData(i, bus, Qt::UserRole);
|
||||
model->setData(i, channel, Qt::UserRole + 1);
|
||||
model->setData(i, icon, Qt::DecorationRole);
|
||||
}
|
||||
|
||||
static void setZIPType(QAbstractItemModel* model, const QModelIndex& idx, bool is250) {
|
||||
auto i = idx.siblingAtColumn(1);
|
||||
model->setData(i, is250 ? "ZIP 250" : "ZIP 100");
|
||||
model->setData(i, is250, Qt::UserRole);
|
||||
}
|
||||
|
||||
SettingsOtherRemovable::SettingsOtherRemovable(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::SettingsOtherRemovable)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
Harddrives::populateRemovableBuses(ui->comboBoxMOBus->model());
|
||||
auto* model = ui->comboBoxMOType->model();
|
||||
for (uint32_t i = 0; i < KNOWN_MO_DRIVE_TYPES; i++) {
|
||||
Models::AddEntry(model, moDriveTypeName(i), i);
|
||||
}
|
||||
|
||||
model = new QStandardItemModel(0, 2, this);
|
||||
ui->tableViewMO->setModel(model);
|
||||
model->setHeaderData(0, Qt::Horizontal, "Bus");
|
||||
model->setHeaderData(1, Qt::Horizontal, "Type");
|
||||
model->insertRows(0, MO_NUM);
|
||||
for (int i = 0; i < MO_NUM; i++) {
|
||||
auto idx = model->index(i, 0);
|
||||
setMOBus(model, idx, mo_drives[i].bus_type, mo_drives[i].res);
|
||||
setMOType(model, idx.siblingAtColumn(1), mo_drives[i].type);
|
||||
}
|
||||
ui->tableViewMO->resizeColumnsToContents();
|
||||
ui->tableViewMO->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
|
||||
connect(ui->tableViewMO->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &SettingsOtherRemovable::onMORowChanged);
|
||||
ui->tableViewMO->setCurrentIndex(model->index(0, 0));
|
||||
|
||||
|
||||
|
||||
|
||||
Harddrives::populateRemovableBuses(ui->comboBoxZIPBus->model());
|
||||
|
||||
model = new QStandardItemModel(0, 2, this);
|
||||
ui->tableViewZIP->setModel(model);
|
||||
model->setHeaderData(0, Qt::Horizontal, "Bus");
|
||||
model->setHeaderData(1, Qt::Horizontal, "Type");
|
||||
model->insertRows(0, ZIP_NUM);
|
||||
for (int i = 0; i < ZIP_NUM; i++) {
|
||||
auto idx = model->index(i, 0);
|
||||
setZIPBus(model, idx, zip_drives[i].bus_type, zip_drives[i].res);
|
||||
setZIPType(model, idx, zip_drives[i].is_250 > 0);
|
||||
}
|
||||
ui->tableViewZIP->resizeColumnsToContents();
|
||||
ui->tableViewZIP->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
|
||||
connect(ui->tableViewZIP->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &SettingsOtherRemovable::onZIPRowChanged);
|
||||
ui->tableViewZIP->setCurrentIndex(model->index(0, 0));
|
||||
}
|
||||
|
||||
SettingsOtherRemovable::~SettingsOtherRemovable()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SettingsOtherRemovable::save() {
|
||||
auto* model = ui->tableViewMO->model();
|
||||
memset(mo_drives, 0, sizeof(mo_drives));
|
||||
for (int i = 0; i < MO_NUM; i++) {
|
||||
mo_drives[i].f = NULL;
|
||||
mo_drives[i].priv = NULL;
|
||||
mo_drives[i].bus_type = model->index(i, 0).data(Qt::UserRole).toUInt();
|
||||
mo_drives[i].res = model->index(i, 0).data(Qt::UserRole + 1).toUInt();
|
||||
mo_drives[i].type = model->index(i, 1).data(Qt::UserRole).toUInt();
|
||||
}
|
||||
|
||||
model = ui->tableViewZIP->model();
|
||||
memset(zip_drives, 0, sizeof(zip_drives));
|
||||
for (int i = 0; i < ZIP_NUM; i++) {
|
||||
zip_drives[i].f = NULL;
|
||||
zip_drives[i].priv = NULL;
|
||||
zip_drives[i].bus_type = model->index(i, 0).data(Qt::UserRole).toUInt();
|
||||
zip_drives[i].res = model->index(i, 0).data(Qt::UserRole + 1).toUInt();
|
||||
zip_drives[i].is_250 = model->index(i, 1).data(Qt::UserRole).toBool() ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsOtherRemovable::onMORowChanged(const QModelIndex ¤t) {
|
||||
uint8_t bus = current.siblingAtColumn(0).data(Qt::UserRole).toUInt();
|
||||
uint8_t channel = current.siblingAtColumn(0).data(Qt::UserRole + 1).toUInt();
|
||||
uint8_t type = current.siblingAtColumn(1).data(Qt::UserRole).toUInt();
|
||||
|
||||
ui->comboBoxMOBus->setCurrentIndex(-1);
|
||||
auto* model = ui->comboBoxMOBus->model();
|
||||
auto match = model->match(model->index(0, 0), Qt::UserRole, bus);
|
||||
if (! match.isEmpty()) {
|
||||
ui->comboBoxMOBus->setCurrentIndex(match.first().row());
|
||||
}
|
||||
|
||||
model = ui->comboBoxMOChannel->model();
|
||||
match = model->match(model->index(0, 0), Qt::UserRole, channel);
|
||||
if (! match.isEmpty()) {
|
||||
ui->comboBoxMOChannel->setCurrentIndex(match.first().row());
|
||||
}
|
||||
ui->comboBoxMOType->setCurrentIndex(type);
|
||||
}
|
||||
|
||||
void SettingsOtherRemovable::onZIPRowChanged(const QModelIndex ¤t) {
|
||||
uint8_t bus = current.siblingAtColumn(0).data(Qt::UserRole).toUInt();
|
||||
uint8_t channel = current.siblingAtColumn(0).data(Qt::UserRole + 1).toUInt();
|
||||
bool is250 = current.siblingAtColumn(1).data(Qt::UserRole).toBool();
|
||||
|
||||
ui->comboBoxZIPBus->setCurrentIndex(-1);
|
||||
auto* model = ui->comboBoxZIPBus->model();
|
||||
auto match = model->match(model->index(0, 0), Qt::UserRole, bus);
|
||||
if (! match.isEmpty()) {
|
||||
ui->comboBoxZIPBus->setCurrentIndex(match.first().row());
|
||||
}
|
||||
|
||||
model = ui->comboBoxZIPChannel->model();
|
||||
match = model->match(model->index(0, 0), Qt::UserRole, channel);
|
||||
if (! match.isEmpty()) {
|
||||
ui->comboBoxZIPChannel->setCurrentIndex(match.first().row());
|
||||
}
|
||||
ui->checkBoxZIP250->setChecked(is250);
|
||||
}
|
||||
|
||||
void SettingsOtherRemovable::on_comboBoxMOBus_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int bus = ui->comboBoxMOBus->currentData().toInt();
|
||||
bool enabled = (bus != MO_BUS_DISABLED);
|
||||
ui->comboBoxMOChannel->setEnabled(enabled);
|
||||
ui->comboBoxMOType->setEnabled(enabled);
|
||||
Harddrives::populateBusChannels(ui->comboBoxMOChannel->model(), bus);
|
||||
}
|
||||
|
||||
void SettingsOtherRemovable::on_comboBoxMOBus_activated(int) {
|
||||
setMOBus(
|
||||
ui->tableViewMO->model(),
|
||||
ui->tableViewMO->selectionModel()->currentIndex(),
|
||||
ui->comboBoxMOBus->currentData().toUInt(),
|
||||
ui->comboBoxMOChannel->currentData().toUInt());
|
||||
setMOType(
|
||||
ui->tableViewMO->model(),
|
||||
ui->tableViewMO->selectionModel()->currentIndex(),
|
||||
ui->comboBoxMOType->currentData().toUInt());
|
||||
ui->tableViewMO->resizeColumnsToContents();
|
||||
ui->tableViewMO->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
}
|
||||
|
||||
void SettingsOtherRemovable::on_comboBoxMOChannel_activated(int) {
|
||||
setMOBus(
|
||||
ui->tableViewMO->model(),
|
||||
ui->tableViewMO->selectionModel()->currentIndex(),
|
||||
ui->comboBoxMOBus->currentData().toUInt(),
|
||||
ui->comboBoxMOChannel->currentData().toUInt());
|
||||
}
|
||||
|
||||
void SettingsOtherRemovable::on_comboBoxMOType_activated(int) {
|
||||
setMOType(
|
||||
ui->tableViewMO->model(),
|
||||
ui->tableViewMO->selectionModel()->currentIndex(),
|
||||
ui->comboBoxMOType->currentData().toUInt());
|
||||
ui->tableViewMO->resizeColumnsToContents();
|
||||
ui->tableViewMO->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
}
|
||||
|
||||
void SettingsOtherRemovable::on_comboBoxZIPBus_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int bus = ui->comboBoxZIPBus->currentData().toInt();
|
||||
bool enabled = (bus != ZIP_BUS_DISABLED);
|
||||
ui->comboBoxZIPChannel->setEnabled(enabled);
|
||||
ui->checkBoxZIP250->setEnabled(enabled);
|
||||
Harddrives::populateBusChannels(ui->comboBoxZIPChannel->model(), bus);
|
||||
}
|
||||
|
||||
void SettingsOtherRemovable::on_comboBoxZIPBus_activated(int) {
|
||||
setZIPBus(
|
||||
ui->tableViewZIP->model(),
|
||||
ui->tableViewZIP->selectionModel()->currentIndex(),
|
||||
ui->comboBoxZIPBus->currentData().toUInt(),
|
||||
ui->comboBoxZIPChannel->currentData().toUInt());
|
||||
}
|
||||
|
||||
void SettingsOtherRemovable::on_comboBoxZIPChannel_activated(int) {
|
||||
setZIPBus(
|
||||
ui->tableViewZIP->model(),
|
||||
ui->tableViewZIP->selectionModel()->currentIndex(),
|
||||
ui->comboBoxZIPBus->currentData().toUInt(),
|
||||
ui->comboBoxZIPChannel->currentData().toUInt());
|
||||
}
|
||||
|
||||
void SettingsOtherRemovable::on_checkBoxZIP250_stateChanged(int state) {
|
||||
setZIPType(
|
||||
ui->tableViewZIP->model(),
|
||||
ui->tableViewZIP->selectionModel()->currentIndex(),
|
||||
state == Qt::Checked);
|
||||
}
|
52
src/qt/qt_settingsotherremovable.hpp
Normal file
52
src/qt/qt_settingsotherremovable.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef QT_SETTINGSOTHERREMOVABLE_HPP
|
||||
#define QT_SETTINGSOTHERREMOVABLE_HPP
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class SettingsOtherRemovable;
|
||||
}
|
||||
|
||||
class SettingsOtherRemovable : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsOtherRemovable(QWidget *parent = nullptr);
|
||||
~SettingsOtherRemovable();
|
||||
|
||||
void save();
|
||||
|
||||
private slots:
|
||||
void on_checkBoxZIP250_stateChanged(int arg1);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxZIPChannel_activated(int index);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxZIPBus_activated(int index);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxZIPBus_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxMOType_activated(int index);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxMOChannel_activated(int index);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxMOBus_activated(int index);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxMOBus_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void onMORowChanged(const QModelIndex ¤t);
|
||||
void onZIPRowChanged(const QModelIndex ¤t);
|
||||
|
||||
private:
|
||||
Ui::SettingsOtherRemovable *ui;
|
||||
};
|
||||
|
||||
#endif // QT_SETTINGSOTHERREMOVABLE_HPP
|
151
src/qt/qt_settingsotherremovable.ui
Normal file
151
src/qt/qt_settingsotherremovable.ui
Normal file
@ -0,0 +1,151 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SettingsOtherRemovable</class>
|
||||
<widget class="QWidget" name="SettingsOtherRemovable">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>418</width>
|
||||
<height>433</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>MO Drives</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="tableViewMO">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Bus</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Channel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxMOBus"/>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QComboBox" name="comboBoxMOChannel"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="3">
|
||||
<widget class="QComboBox" name="comboBoxMOType"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>ZIP Drives</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="tableViewZIP">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Bus</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxZIPBus"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Channel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBoxZIPChannel"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxZIP250">
|
||||
<property name="text">
|
||||
<string>ZIP 250</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
81
src/qt/qt_settingsports.cpp
Normal file
81
src/qt/qt_settingsports.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include "qt_settingsports.hpp"
|
||||
#include "ui_qt_settingsports.h"
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/lpt.h>
|
||||
}
|
||||
|
||||
#include "qt_deviceconfig.hpp"
|
||||
#include "qt_models_common.hpp"
|
||||
|
||||
SettingsPorts::SettingsPorts(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::SettingsPorts)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
auto* cbox = findChild<QComboBox*>(QString("comboBoxLpt%1").arg(i+1));
|
||||
auto* model = cbox->model();
|
||||
int c = 0;
|
||||
int selectedRow = 0;
|
||||
while (true) {
|
||||
const char* lptName = lpt_device_get_name(c);
|
||||
if (lptName == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
Models::AddEntry(model, lptName, c);
|
||||
if (c == lpt_ports[i].device) {
|
||||
selectedRow = c;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
cbox->setCurrentIndex(selectedRow);
|
||||
|
||||
auto* checkBox = findChild<QCheckBox*>(QString("checkBoxParallel%1").arg(i+1));
|
||||
checkBox->setChecked(lpt_ports[i].enabled > 0);
|
||||
cbox->setEnabled(lpt_ports[i].enabled > 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
auto* checkBox = findChild<QCheckBox*>(QString("checkBoxSerial%1").arg(i+1));
|
||||
checkBox->setChecked(serial_enabled[i] > 0);
|
||||
}
|
||||
}
|
||||
|
||||
SettingsPorts::~SettingsPorts()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SettingsPorts::save() {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
auto* cbox = findChild<QComboBox*>(QString("comboBoxLpt%1").arg(i+1));
|
||||
auto* checkBox = findChild<QCheckBox*>(QString("checkBoxParallel%1").arg(i+1));
|
||||
lpt_ports[i].device = cbox->currentData().toInt();
|
||||
lpt_ports[i].enabled = checkBox->isChecked() ? 1 : 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
auto* checkBox = findChild<QCheckBox*>(QString("checkBoxSerial%1").arg(i+1));
|
||||
serial_enabled[i] = checkBox->isChecked() ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsPorts::on_checkBoxParallel1_stateChanged(int state) {
|
||||
ui->comboBoxLpt1->setEnabled(state == Qt::Checked);
|
||||
}
|
||||
|
||||
void SettingsPorts::on_checkBoxParallel2_stateChanged(int state) {
|
||||
ui->comboBoxLpt2->setEnabled(state == Qt::Checked);
|
||||
}
|
||||
|
||||
void SettingsPorts::on_checkBoxParallel3_stateChanged(int state) {
|
||||
ui->comboBoxLpt3->setEnabled(state == Qt::Checked);
|
||||
}
|
||||
|
28
src/qt/qt_settingsports.hpp
Normal file
28
src/qt/qt_settingsports.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef QT_SETTINGSPORTS_HPP
|
||||
#define QT_SETTINGSPORTS_HPP
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class SettingsPorts;
|
||||
}
|
||||
|
||||
class SettingsPorts : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsPorts(QWidget *parent = nullptr);
|
||||
~SettingsPorts();
|
||||
|
||||
void save();
|
||||
private slots:
|
||||
void on_checkBoxParallel3_stateChanged(int arg1);
|
||||
void on_checkBoxParallel2_stateChanged(int arg1);
|
||||
void on_checkBoxParallel1_stateChanged(int arg1);
|
||||
|
||||
private:
|
||||
Ui::SettingsPorts *ui;
|
||||
};
|
||||
|
||||
#endif // QT_SETTINGSPORTS_HPP
|
133
src/qt/qt_settingsports.ui
Normal file
133
src/qt/qt_settingsports.ui
Normal file
@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SettingsPorts</class>
|
||||
<widget class="QWidget" name="SettingsPorts">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>398</width>
|
||||
<height>341</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>LPT1 Device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxLpt1"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>LPT2 Device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBoxLpt2"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>LPT3 Device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboBoxLpt3"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerial1">
|
||||
<property name="text">
|
||||
<string>Serial Port 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="checkBoxParallel1">
|
||||
<property name="text">
|
||||
<string>Parallel Port 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerial2">
|
||||
<property name="text">
|
||||
<string>Serial Port 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="checkBoxParallel2">
|
||||
<property name="text">
|
||||
<string>Parallel Port 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerial3">
|
||||
<property name="text">
|
||||
<string>Serial Port 3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="checkBoxParallel3">
|
||||
<property name="text">
|
||||
<string>Parallel Port 3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxSerial4">
|
||||
<property name="text">
|
||||
<string>Serial Port 4</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
223
src/qt/qt_settingssound.cpp
Normal file
223
src/qt/qt_settingssound.cpp
Normal file
@ -0,0 +1,223 @@
|
||||
#include "qt_settingssound.hpp"
|
||||
#include "ui_qt_settingssound.h"
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/sound.h>
|
||||
#include <86box/midi.h>
|
||||
#include <86box/snd_mpu401.h>
|
||||
}
|
||||
|
||||
#include "qt_deviceconfig.hpp"
|
||||
#include "qt_models_common.hpp"
|
||||
|
||||
SettingsSound::SettingsSound(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::SettingsSound)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
onCurrentMachineChanged(machine);
|
||||
}
|
||||
|
||||
SettingsSound::~SettingsSound()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SettingsSound::save() {
|
||||
sound_card_current = ui->comboBoxSoundCard->currentData().toInt();
|
||||
midi_device_current = ui->comboBoxMidiOut->currentData().toInt();
|
||||
midi_input_device_current = ui->comboBoxMidiIn->currentData().toInt();
|
||||
mpu401_standalone_enable = ui->checkBoxMPU401->isChecked() ? 1 : 0;
|
||||
SSI2001 = ui->checkBoxSSI2001->isChecked() ? 1 : 0;;
|
||||
GAMEBLASTER = ui->checkBoxCMS->isChecked() ? 1 : 0;
|
||||
GUS = ui->checkBoxGUS->isChecked() ? 1 : 0;;
|
||||
sound_is_float = ui->checkBoxFloat32->isChecked() ? 1 : 0;;
|
||||
}
|
||||
|
||||
void SettingsSound::onCurrentMachineChanged(int machineId) {
|
||||
this->machineId = machineId;
|
||||
auto* machine = &machines[machineId];
|
||||
|
||||
auto* model = ui->comboBoxSoundCard->model();
|
||||
auto removeRows = model->rowCount();
|
||||
int c = 0;
|
||||
int selectedRow = 0;
|
||||
while (true) {
|
||||
/* Skip "internal" if machine doesn't have it. */
|
||||
if ((c == 1) && !(machine->flags & MACHINE_SOUND)) {
|
||||
c++;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* sound_dev = sound_card_getdevice(c);
|
||||
QString name = DeviceConfig::DeviceName(sound_dev, sound_card_get_internal_name(c), 1);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (sound_card_available(c)) {
|
||||
if (device_is_valid(sound_dev, machine->flags)) {
|
||||
int row = Models::AddEntry(model, name, c);
|
||||
if (c == sound_card_current) {
|
||||
selectedRow = row - removeRows;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c++;
|
||||
}
|
||||
model->removeRows(0, removeRows);
|
||||
ui->comboBoxSoundCard->setEnabled(model->rowCount() > 0);
|
||||
ui->comboBoxSoundCard->setCurrentIndex(-1);
|
||||
ui->comboBoxSoundCard->setCurrentIndex(selectedRow);
|
||||
|
||||
model = ui->comboBoxMidiOut->model();
|
||||
removeRows = model->rowCount();
|
||||
c = 0;
|
||||
selectedRow = 0;
|
||||
while (true) {
|
||||
QString name = DeviceConfig::DeviceName(midi_device_getdevice(c), midi_device_get_internal_name(c), 0);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (midi_device_available(c)) {
|
||||
int row = Models::AddEntry(model, name, c);
|
||||
if (c == midi_input_device_current) {
|
||||
selectedRow = row - removeRows;
|
||||
}
|
||||
}
|
||||
c++;
|
||||
}
|
||||
model->removeRows(0, removeRows);
|
||||
ui->comboBoxMidiOut->setEnabled(model->rowCount() > 0);
|
||||
ui->comboBoxMidiOut->setCurrentIndex(-1);
|
||||
ui->comboBoxMidiOut->setCurrentIndex(selectedRow);
|
||||
|
||||
model = ui->comboBoxMidiIn->model();
|
||||
removeRows = model->rowCount();
|
||||
c = 0;
|
||||
selectedRow = 0;
|
||||
while (true) {
|
||||
QString name = DeviceConfig::DeviceName(midi_in_device_getdevice(c), midi_device_get_internal_name(c), 0);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (midi_in_device_available(c)) {
|
||||
int row = Models::AddEntry(model, name, c);
|
||||
if (c == midi_device_current) {
|
||||
selectedRow = row - removeRows;
|
||||
}
|
||||
}
|
||||
|
||||
c++;
|
||||
}
|
||||
model->removeRows(0, removeRows);
|
||||
ui->comboBoxMidiIn->setEnabled(model->rowCount() > 0);
|
||||
ui->comboBoxMidiIn->setCurrentIndex(-1);
|
||||
ui->comboBoxMidiIn->setCurrentIndex(selectedRow);
|
||||
|
||||
ui->checkBoxMPU401->setChecked(mpu401_standalone_enable > 0);
|
||||
ui->checkBoxSSI2001->setChecked(SSI2001 > 0);
|
||||
ui->checkBoxCMS->setChecked(GAMEBLASTER > 0);
|
||||
ui->checkBoxGUS->setChecked(GUS > 0);
|
||||
ui->checkBoxFloat32->setChecked(sound_is_float > 0);
|
||||
|
||||
ui->pushButtonConfigureSSI2001->setEnabled((SSI2001 > 0) && (machine->flags & MACHINE_BUS_ISA));
|
||||
ui->pushButtonConfigureCMS->setEnabled((GAMEBLASTER > 0) && (machine->flags & MACHINE_BUS_ISA));
|
||||
ui->pushButtonConfigureGUS->setEnabled((GUS > 0) && (machine->flags & MACHINE_BUS_ISA16));
|
||||
}
|
||||
|
||||
static bool allowMpu401(Ui::SettingsSound *ui) {
|
||||
QString midiOut = midi_device_get_internal_name(ui->comboBoxMidiOut->currentData().toInt());
|
||||
QString midiIn = midi_in_device_get_internal_name(ui->comboBoxMidiIn->currentData().toInt());
|
||||
|
||||
if (midiOut.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (midiOut == QStringLiteral("none") && midiIn == QStringLiteral("none")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SettingsSound::on_comboBoxSoundCard_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
ui->pushButtonConfigureSoundCard->setEnabled(sound_card_has_config(ui->comboBoxSoundCard->currentData().toInt()));
|
||||
}
|
||||
|
||||
|
||||
void SettingsSound::on_pushButtonConfigureSoundCard_clicked() {
|
||||
DeviceConfig::ConfigureDevice(sound_card_getdevice(ui->comboBoxSoundCard->currentData().toInt()));
|
||||
}
|
||||
|
||||
void SettingsSound::on_comboBoxMidiOut_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
ui->pushButtonConfigureMidiOut->setEnabled(midi_device_has_config(ui->comboBoxMidiOut->currentData().toInt()));
|
||||
ui->checkBoxMPU401->setEnabled(allowMpu401(ui));
|
||||
ui->pushButtonConfigureMPU401->setEnabled(allowMpu401(ui) && ui->checkBoxMPU401->isChecked());
|
||||
}
|
||||
|
||||
void SettingsSound::on_pushButtonConfigureMidiOut_clicked() {
|
||||
DeviceConfig::ConfigureDevice(midi_device_getdevice(ui->comboBoxMidiOut->currentData().toInt()));
|
||||
}
|
||||
|
||||
void SettingsSound::on_comboBoxMidiIn_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
ui->pushButtonConfigureMidiIn->setEnabled(midi_in_device_has_config(ui->comboBoxMidiIn->currentData().toInt()));
|
||||
ui->checkBoxMPU401->setEnabled(allowMpu401(ui));
|
||||
ui->pushButtonConfigureMPU401->setEnabled(allowMpu401(ui) && ui->checkBoxMPU401->isChecked());
|
||||
}
|
||||
|
||||
void SettingsSound::on_pushButtonConfigureMidiIn_clicked() {
|
||||
DeviceConfig::ConfigureDevice(midi_in_device_getdevice(ui->comboBoxMidiIn->currentData().toInt()));
|
||||
}
|
||||
|
||||
void SettingsSound::on_checkBoxMPU401_stateChanged(int state) {
|
||||
ui->pushButtonConfigureMPU401->setEnabled(state == Qt::Checked);
|
||||
}
|
||||
|
||||
void SettingsSound::on_checkBoxSSI2001_stateChanged(int state) {
|
||||
ui->pushButtonConfigureSSI2001->setEnabled(state == Qt::Checked);
|
||||
}
|
||||
|
||||
void SettingsSound::on_checkBoxCMS_stateChanged(int state) {
|
||||
ui->pushButtonConfigureCMS->setEnabled(state == Qt::Checked);
|
||||
}
|
||||
|
||||
void SettingsSound::on_checkBoxGUS_stateChanged(int state) {
|
||||
ui->pushButtonConfigureGUS->setEnabled(state == Qt::Checked);
|
||||
}
|
||||
|
||||
void SettingsSound::on_pushButtonConfigureMPU401_clicked() {
|
||||
if (machines[machineId].flags & MACHINE_MCA) {
|
||||
DeviceConfig::ConfigureDevice(&mpu401_mca_device);
|
||||
} else {
|
||||
DeviceConfig::ConfigureDevice(&mpu401_device);
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsSound::on_pushButtonConfigureSSI2001_clicked() {
|
||||
DeviceConfig::ConfigureDevice(&ssi2001_device);
|
||||
}
|
||||
|
||||
void SettingsSound::on_pushButtonConfigureCMS_clicked() {
|
||||
DeviceConfig::ConfigureDevice(&cms_device);
|
||||
}
|
||||
|
||||
void SettingsSound::on_pushButtonConfigureGUS_clicked() {
|
||||
DeviceConfig::ConfigureDevice(&gus_device);
|
||||
}
|
44
src/qt/qt_settingssound.hpp
Normal file
44
src/qt/qt_settingssound.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef QT_SETTINGSSOUND_HPP
|
||||
#define QT_SETTINGSSOUND_HPP
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class SettingsSound;
|
||||
}
|
||||
|
||||
class SettingsSound : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsSound(QWidget *parent = nullptr);
|
||||
~SettingsSound();
|
||||
|
||||
void save();
|
||||
|
||||
public slots:
|
||||
void onCurrentMachineChanged(int machineId);
|
||||
|
||||
private slots:
|
||||
void on_pushButtonConfigureGUS_clicked();
|
||||
void on_pushButtonConfigureCMS_clicked();
|
||||
void on_pushButtonConfigureSSI2001_clicked();
|
||||
void on_pushButtonConfigureMPU401_clicked();
|
||||
void on_checkBoxGUS_stateChanged(int arg1);
|
||||
void on_checkBoxCMS_stateChanged(int arg1);
|
||||
void on_checkBoxSSI2001_stateChanged(int arg1);
|
||||
void on_checkBoxMPU401_stateChanged(int arg1);
|
||||
void on_pushButtonConfigureMidiIn_clicked();
|
||||
void on_pushButtonConfigureMidiOut_clicked();
|
||||
void on_comboBoxMidiIn_currentIndexChanged(int index);
|
||||
void on_comboBoxMidiOut_currentIndexChanged(int index);
|
||||
void on_pushButtonConfigureSoundCard_clicked();
|
||||
void on_comboBoxSoundCard_currentIndexChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::SettingsSound *ui;
|
||||
int machineId = 0;
|
||||
};
|
||||
|
||||
#endif // QT_SETTINGSSOUND_HPP
|
160
src/qt/qt_settingssound.ui
Normal file
160
src/qt/qt_settingssound.ui
Normal file
@ -0,0 +1,160 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SettingsSound</class>
|
||||
<widget class="QWidget" name="SettingsSound">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>387</width>
|
||||
<height>332</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>MIDI In</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBoxSSI2001">
|
||||
<property name="text">
|
||||
<string>Innovation SSI-2001</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxGUS">
|
||||
<property name="text">
|
||||
<string>Gravis Ultrasound</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Sound Card</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QPushButton" name="pushButtonConfigureSoundCard">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="comboBoxMidiIn"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>MIDI Out</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxMPU401">
|
||||
<property name="text">
|
||||
<string>Standalone MPU-401</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QPushButton" name="pushButtonConfigureMPU401">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QPushButton" name="pushButtonConfigureMidiIn">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QPushButton" name="pushButtonConfigureSSI2001">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxCMS">
|
||||
<property name="text">
|
||||
<string>CMS / Game Blaster</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxSoundCard"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBoxMidiOut"/>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QPushButton" name="pushButtonConfigureMidiOut">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxFloat32">
|
||||
<property name="text">
|
||||
<string>Use FLOAT32 sound</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<widget class="QPushButton" name="pushButtonConfigureCMS">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="3">
|
||||
<widget class="QPushButton" name="pushButtonConfigureGUS">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
233
src/qt/qt_settingsstoragecontrollers.cpp
Normal file
233
src/qt/qt_settingsstoragecontrollers.cpp
Normal file
@ -0,0 +1,233 @@
|
||||
#include "qt_settingsstoragecontrollers.hpp"
|
||||
#include "ui_qt_settingsstoragecontrollers.h"
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/hdc_ide.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/scsi.h>
|
||||
#include <86box/scsi_device.h>
|
||||
#include <86box/cassette.h>
|
||||
}
|
||||
|
||||
#include "qt_deviceconfig.hpp"
|
||||
#include "qt_models_common.hpp"
|
||||
|
||||
SettingsStorageControllers::SettingsStorageControllers(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::SettingsStorageControllers)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->checkBoxCassette->setChecked(cassette_enable > 0);
|
||||
|
||||
onCurrentMachineChanged(machine);
|
||||
}
|
||||
|
||||
SettingsStorageControllers::~SettingsStorageControllers()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::save() {
|
||||
/* Storage devices category */
|
||||
for (int i = 0; i < SCSI_BUS_MAX; ++i) {
|
||||
auto* cbox = findChild<QComboBox*>(QString("comboBoxSCSI%1").arg(i+1));
|
||||
scsi_card_current[i] = cbox->currentData().toInt();
|
||||
}
|
||||
hdc_current = ui->comboBoxHD->currentData().toInt();
|
||||
fdc_type = ui->comboBoxFD->currentData().toInt();
|
||||
ide_ter_enabled = ui->checkBoxTertiaryIDE->isChecked() ? 1 : 0;
|
||||
ide_qua_enabled = ui->checkBoxQuaternaryIDE->isChecked() ? 1 : 0;
|
||||
cassette_enable = ui->checkBoxCassette->isChecked() ? 1 : 0;
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::onCurrentMachineChanged(int machineId) {
|
||||
this->machineId = machineId;
|
||||
auto* machine = &machines[machineId];
|
||||
|
||||
/*HD controller config*/
|
||||
auto* model = ui->comboBoxHD->model();
|
||||
auto removeRows = model->rowCount();
|
||||
int c = 0;
|
||||
int selectedRow = 0;
|
||||
while (true) {
|
||||
/* Skip "internal" if machine doesn't have it. */
|
||||
if ((c == 1) && !(machine->flags & MACHINE_HDC)) {
|
||||
c++;
|
||||
continue;
|
||||
}
|
||||
|
||||
QString name = DeviceConfig::DeviceName(hdc_get_device(c), hdc_get_internal_name(c), 1);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (hdc_available(c)) {
|
||||
auto* hdc_dev = hdc_get_device(c);
|
||||
|
||||
if (device_is_valid(hdc_dev, machine->flags)) {
|
||||
int row = Models::AddEntry(model, name, c);
|
||||
if (c == hdc_current) {
|
||||
selectedRow = row - removeRows;
|
||||
}
|
||||
}
|
||||
}
|
||||
c++;
|
||||
}
|
||||
model->removeRows(0, removeRows);
|
||||
ui->comboBoxHD->setEnabled(model->rowCount() > 0);
|
||||
ui->comboBoxHD->setCurrentIndex(-1);
|
||||
ui->comboBoxHD->setCurrentIndex(selectedRow);
|
||||
|
||||
/*FD controller config*/
|
||||
model = ui->comboBoxFD->model();
|
||||
removeRows = model->rowCount();
|
||||
c = 0;
|
||||
selectedRow = 0;
|
||||
while (true) {
|
||||
QString name = DeviceConfig::DeviceName(fdc_card_getdevice(c), fdc_card_get_internal_name(c), 1);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (fdc_card_available(c)) {
|
||||
auto* fdc_dev = fdc_card_getdevice(c);
|
||||
|
||||
if (device_is_valid(fdc_dev, machine->flags)) {
|
||||
int row = Models::AddEntry(model, name, c);
|
||||
if (c == fdc_type) {
|
||||
selectedRow = row - removeRows;
|
||||
}
|
||||
}
|
||||
}
|
||||
c++;
|
||||
}
|
||||
model->removeRows(0, removeRows);
|
||||
ui->comboBoxFD->setEnabled(model->rowCount() > 0);
|
||||
ui->comboBoxFD->setCurrentIndex(-1);
|
||||
ui->comboBoxFD->setCurrentIndex(selectedRow);
|
||||
|
||||
for (int i = 0; i < SCSI_BUS_MAX; ++i) {
|
||||
auto* cbox = findChild<QComboBox*>(QString("comboBoxSCSI%1").arg(i+1));
|
||||
model = cbox->model();
|
||||
removeRows = model->rowCount();
|
||||
c = 0;
|
||||
selectedRow = 0;
|
||||
|
||||
while (true) {
|
||||
auto name = DeviceConfig::DeviceName(scsi_card_getdevice(c), scsi_card_get_internal_name(c), 1);
|
||||
if (name.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (scsi_card_available(c)) {
|
||||
auto* scsi_dev = scsi_card_getdevice(c);
|
||||
if (device_is_valid(scsi_dev, machine->flags)) {
|
||||
int row = Models::AddEntry(model, name, c);
|
||||
if (c == scsi_card_current[i]) {
|
||||
selectedRow = row - removeRows;
|
||||
}
|
||||
}
|
||||
}
|
||||
c++;
|
||||
}
|
||||
|
||||
model->removeRows(0, removeRows);
|
||||
cbox->setEnabled(model->rowCount() > 0);
|
||||
cbox->setCurrentIndex(-1);
|
||||
cbox->setCurrentIndex(selectedRow);
|
||||
}
|
||||
|
||||
int is_at = IS_AT(machineId);
|
||||
ui->checkBoxTertiaryIDE->setEnabled(is_at > 0);
|
||||
ui->checkBoxQuaternaryIDE->setEnabled(is_at > 0);
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_comboBoxHD_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
ui->pushButtonHD->setEnabled(hdc_has_config(ui->comboBoxHD->currentData().toInt()) > 0);
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_comboBoxFD_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
ui->pushButtonFD->setEnabled(hdc_has_config(ui->comboBoxFD->currentData().toInt()) > 0);
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_checkBoxTertiaryIDE_stateChanged(int arg1) {
|
||||
ui->pushButtonTertiaryIDE->setEnabled(arg1 == Qt::Checked);
|
||||
}
|
||||
|
||||
|
||||
void SettingsStorageControllers::on_checkBoxQuaternaryIDE_stateChanged(int arg1) {
|
||||
ui->pushButtonQuaternaryIDE->setEnabled(arg1 == Qt::Checked);
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_pushButtonHD_clicked() {
|
||||
DeviceConfig::ConfigureDevice(hdc_get_device(ui->comboBoxHD->currentData().toInt()));
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_pushButtonFD_clicked() {
|
||||
DeviceConfig::ConfigureDevice(fdc_card_getdevice(ui->comboBoxFD->currentData().toInt()));
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_pushButtonTertiaryIDE_clicked() {
|
||||
DeviceConfig::ConfigureDevice(&ide_ter_device);
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_pushButtonQuaternaryIDE_clicked() {
|
||||
DeviceConfig::ConfigureDevice(&ide_qua_device);
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_comboBoxSCSI1_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
ui->pushButtonSCSI1->setEnabled(scsi_card_has_config(ui->comboBoxSCSI1->currentData().toInt()) > 0);
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_comboBoxSCSI2_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
ui->pushButtonSCSI2->setEnabled(scsi_card_has_config(ui->comboBoxSCSI2->currentData().toInt()) > 0);
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_comboBoxSCSI3_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
ui->pushButtonSCSI3->setEnabled(scsi_card_has_config(ui->comboBoxSCSI3->currentData().toInt()) > 0);
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_comboBoxSCSI4_currentIndexChanged(int index) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
ui->pushButtonSCSI4->setEnabled(scsi_card_has_config(ui->comboBoxSCSI4->currentData().toInt()) > 0);
|
||||
}
|
||||
|
||||
|
||||
void SettingsStorageControllers::on_pushButtonSCSI1_clicked() {
|
||||
DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI1->currentData().toInt()));
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_pushButtonSCSI2_clicked() {
|
||||
DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI2->currentData().toInt()));
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_pushButtonSCSI3_clicked() {
|
||||
DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI3->currentData().toInt()));
|
||||
}
|
||||
|
||||
void SettingsStorageControllers::on_pushButtonSCSI4_clicked() {
|
||||
DeviceConfig::ConfigureDevice(scsi_card_getdevice(ui->comboBoxSCSI4->currentData().toInt()));
|
||||
}
|
76
src/qt/qt_settingsstoragecontrollers.hpp
Normal file
76
src/qt/qt_settingsstoragecontrollers.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef QT_SETTINGSSTORAGECONTROLLERS_HPP
|
||||
#define QT_SETTINGSSTORAGECONTROLLERS_HPP
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class SettingsStorageControllers;
|
||||
}
|
||||
|
||||
class SettingsStorageControllers : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsStorageControllers(QWidget *parent = nullptr);
|
||||
~SettingsStorageControllers();
|
||||
|
||||
void save();
|
||||
|
||||
public slots:
|
||||
void onCurrentMachineChanged(int machineId);
|
||||
|
||||
private slots:
|
||||
void on_pushButtonSCSI4_clicked();
|
||||
|
||||
private slots:
|
||||
void on_pushButtonSCSI3_clicked();
|
||||
|
||||
private slots:
|
||||
void on_pushButtonSCSI2_clicked();
|
||||
|
||||
private slots:
|
||||
void on_pushButtonSCSI1_clicked();
|
||||
|
||||
private slots:
|
||||
void on_comboBoxSCSI4_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxSCSI3_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxSCSI2_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxSCSI1_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void on_pushButtonQuaternaryIDE_clicked();
|
||||
|
||||
private slots:
|
||||
void on_pushButtonTertiaryIDE_clicked();
|
||||
|
||||
private slots:
|
||||
void on_pushButtonFD_clicked();
|
||||
|
||||
private slots:
|
||||
void on_pushButtonHD_clicked();
|
||||
|
||||
private slots:
|
||||
void on_checkBoxQuaternaryIDE_stateChanged(int arg1);
|
||||
|
||||
private slots:
|
||||
void on_checkBoxTertiaryIDE_stateChanged(int arg1);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxFD_currentIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void on_comboBoxHD_currentIndexChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::SettingsStorageControllers *ui;
|
||||
int machineId = 0;
|
||||
};
|
||||
|
||||
#endif // QT_SETTINGSSTORAGECONTROLLERS_HPP
|
202
src/qt/qt_settingsstoragecontrollers.ui
Normal file
202
src/qt/qt_settingsstoragecontrollers.ui
Normal file
@ -0,0 +1,202 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SettingsStorageControllers</class>
|
||||
<widget class="QWidget" name="SettingsStorageControllers">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>496</width>
|
||||
<height>449</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>HD Controller</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="pushButtonFD">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>FD Controller</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxHD"/>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="pushButtonHD">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBoxFD"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxTertiaryIDE">
|
||||
<property name="text">
|
||||
<string>Tertiary IDE Controller</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxQuaternaryIDE">
|
||||
<property name="text">
|
||||
<string>Quaternary IDE Controller</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="pushButtonTertiaryIDE">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="pushButtonQuaternaryIDE">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>SCSI</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="3" column="2">
|
||||
<widget class="QComboBox" name="comboBoxSCSI4"/>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QPushButton" name="pushButtonSCSI4">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Controller 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QComboBox" name="comboBoxSCSI1"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QComboBox" name="comboBoxSCSI2"/>
|
||||
</item>
|
||||
<item row="3" column="0" rowspan="2">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Controller 4</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Controller 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QPushButton" name="pushButtonSCSI1">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QPushButton" name="pushButtonSCSI2">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Controller 3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QComboBox" name="comboBoxSCSI3"/>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QPushButton" name="pushButtonSCSI3">
|
||||
<property name="text">
|
||||
<string>Configure</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxCassette">
|
||||
<property name="text">
|
||||
<string>Cassette</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
111
src/qt/qt_ui.cpp
Normal file
111
src/qt/qt_ui.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
#include <cstdint>
|
||||
|
||||
#include <QThread>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <QStatusBar>
|
||||
|
||||
#include "qt_mainwindow.hpp"
|
||||
|
||||
std::atomic_int resize_pending = 0;
|
||||
std::atomic_int resize_w = 0;
|
||||
std::atomic_int resize_h = 0;
|
||||
|
||||
MainWindow* main_window = nullptr;
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include <86box/plat.h>
|
||||
|
||||
void
|
||||
ui_sb_update_icon_state(int tag, int state)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ui_sb_update_icon(int tag, int active)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
plat_delay_ms(uint32_t count)
|
||||
{
|
||||
QThread::msleep(count);
|
||||
}
|
||||
|
||||
void
|
||||
ui_sb_update_tip(int arg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ui_sb_update_panes()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ui_sb_bugui(char *str)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ui_sb_set_ready(int ready) {}
|
||||
|
||||
wchar_t* ui_window_title(wchar_t* str)
|
||||
{
|
||||
if (str == nullptr) {
|
||||
static wchar_t title[512];
|
||||
int chars = main_window->windowTitle().toWCharArray(title);
|
||||
title[chars] = 0;
|
||||
str = title;
|
||||
} else {
|
||||
main_window->setWindowTitle(QString::fromWCharArray(str));
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
void mouse_poll() {
|
||||
main_window->pollMouse();
|
||||
}
|
||||
|
||||
void plat_resize(int w, int h) {
|
||||
resize_w = w;
|
||||
resize_h = h;
|
||||
resize_pending = 1;
|
||||
|
||||
main_window->resizeContents(w, h);
|
||||
}
|
||||
|
||||
void plat_setfullscreen(int on) {
|
||||
main_window->setFullscreen(on > 0 ? true : false);
|
||||
}
|
||||
|
||||
void plat_mouse_capture(int on) {
|
||||
main_window->setMouseCapture(on > 0 ? true : false);
|
||||
}
|
||||
|
||||
int ui_msgbox_header(int flags, void *header, void* message)
|
||||
{
|
||||
if (header <= (void*)7168) header = plat_get_string(reinterpret_cast<long>(header));
|
||||
if (message <= (void*)7168) message = plat_get_string(reinterpret_cast<long>(message));
|
||||
|
||||
auto hdr = QString::fromWCharArray(reinterpret_cast<const wchar_t*>(header));
|
||||
auto msg = QString::fromWCharArray(reinterpret_cast<const wchar_t*>(message));
|
||||
|
||||
QMessageBox box(QMessageBox::Warning, hdr, msg);
|
||||
box.exec();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ui_msgbox(int flags, void *message) {
|
||||
return ui_msgbox_header(flags, nullptr, message);
|
||||
}
|
||||
|
||||
void ui_sb_set_text_w(wchar_t *wstr) {
|
||||
main_window->statusBar()->showMessage(QString::fromWCharArray(wstr));
|
||||
}
|
||||
|
||||
}
|
24
src/qt_resources.qrc
Normal file
24
src/qt_resources.qrc
Normal file
@ -0,0 +1,24 @@
|
||||
<RCC>
|
||||
<qresource prefix="/settings">
|
||||
<file>win/icons/machine.ico</file>
|
||||
<file>win/icons/display.ico</file>
|
||||
<file>win/icons/input_devices.ico</file>
|
||||
<file>win/icons/sound.ico</file>
|
||||
<file>win/icons/network.ico</file>
|
||||
<file>win/icons/ports.ico</file>
|
||||
<file>win/icons/storage_controllers.ico</file>
|
||||
<file>win/icons/hard_disk.ico</file>
|
||||
<file>win/icons/floppy_and_cdrom_drives.ico</file>
|
||||
<file>win/icons/other_peripherals.ico</file>
|
||||
<file>win/icons/other_removable_devices.ico</file>
|
||||
<file>win/icons/floppy_35.ico</file>
|
||||
<file>win/icons/floppy_525.ico</file>
|
||||
<file>win/icons/floppy_disabled.ico</file>
|
||||
<file>win/icons/cdrom_disabled.ico</file>
|
||||
<file>win/icons/cdrom.ico</file>
|
||||
<file>win/icons/mo.ico</file>
|
||||
<file>win/icons/mo_disabled.ico</file>
|
||||
<file>win/icons/zip.ico</file>
|
||||
<file>win/icons/zip_disabled.ico</file>
|
||||
</qresource>
|
||||
</RCC>
|
Loading…
x
Reference in New Issue
Block a user