2022-02-07 15:00:02 +06:00
/*
2023-01-06 15:36:05 -05:00
* 86 Box 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 .
2022-02-07 15:00:02 +06:00
*
2023-01-06 15:36:05 -05:00
* This file is part of the 86 Box distribution .
2022-02-07 15:00:02 +06:00
*
2023-01-06 15:36:05 -05:00
* Main entry point module
2022-02-07 15:00:02 +06:00
*
*
2023-01-06 15:36:05 -05:00
* Authors : Joakim L . Gilje < jgilje @ jgilje . net >
2022-02-07 15:00:02 +06:00
* Cacodemon345
* Teemu Korhonen
*
2023-01-06 15:36:05 -05:00
* Copyright 2021 Joakim L . Gilje
* Copyright 2021 - 2022 Cacodemon345
* Copyright 2021 - 2022 Teemu Korhonen
2022-02-07 15:00:02 +06:00
*/
2021-11-25 10:20:56 +01:00
# include <QApplication>
2021-12-25 15:34:00 +06:00
# include <QSurfaceFormat>
2021-11-25 10:20:56 +01:00
# include <QDebug>
# include <QElapsedTimer>
# include <QThread>
# include <QTimer>
2021-12-31 12:36:55 +06:00
# include <QTranslator>
# include <QDirIterator>
# include <QLibraryInfo>
2022-02-12 01:50:04 +06:00
# include <QString>
2022-02-12 01:50:50 +06:00
# include <QFont>
2023-10-06 01:18:16 +05:00
# include <QDialog>
# include <QMessageBox>
2024-03-29 08:23:55 -04:00
# include <QPushButton>
2021-11-25 10:20:56 +01:00
2021-12-06 17:31:25 +02:00
# ifdef QT_STATIC
/* Static builds need plugin imports */
2022-11-19 08:49:04 -05:00
# include <QtPlugin>
2021-12-06 17:31:25 +02:00
Q_IMPORT_PLUGIN ( QICOPlugin )
2022-11-19 08:49:04 -05:00
# ifdef Q_OS_WINDOWS
2021-12-06 17:31:25 +02:00
Q_IMPORT_PLUGIN ( QWindowsIntegrationPlugin )
Q_IMPORT_PLUGIN ( QWindowsVistaStylePlugin )
2022-11-19 08:49:04 -05:00
# endif
2021-12-06 17:31:25 +02:00
# endif
2021-12-09 20:59:50 +02:00
# ifdef Q_OS_WINDOWS
2025-01-03 00:15:28 +01:00
# include "qt_rendererstack.hpp"
2022-11-19 08:49:04 -05:00
# include "qt_winrawinputfilter.hpp"
# include "qt_winmanagerfilter.hpp"
# include <86box / win.h>
2023-02-14 20:37:58 -05:00
# include <shobjidl.h>
2024-12-31 00:48:50 +01:00
# include <windows.h>
2021-12-09 20:59:50 +02:00
# endif
2022-11-19 08:49:04 -05:00
extern " C " {
2021-11-25 10:20:56 +01:00
# include <86box/86box.h>
2022-02-06 12:45:55 +06:00
# include <86box/config.h>
2021-11-25 10:20:56 +01:00
# include <86box/plat.h>
# include <86box/ui.h>
# include <86box/video.h>
2023-02-01 17:17:56 +01:00
# ifdef DISCORD
# include <86box / discord.h>
# endif
2022-03-16 00:33:01 -03:00
# include <86box/gdbstub.h>
2024-03-10 18:01:09 -03:00
# include <86box/version.h>
2022-02-06 12:45:55 +06:00
}
2021-11-25 10:20:56 +01:00
# include <thread>
2021-12-31 12:36:55 +06:00
# include <iostream>
2022-01-22 01:10:11 +02:00
# include <memory>
2021-11-25 10:20:56 +01:00
# include "qt_mainwindow.hpp"
2022-01-08 16:39:51 +06:00
# include "qt_progsettings.hpp"
2022-02-06 12:45:55 +06:00
# include "qt_settings.hpp"
2021-11-30 16:26:49 +06:00
# include "cocoa_mouse.hpp"
2021-12-12 18:19:44 +02:00
# include "qt_styleoverride.hpp"
2022-02-27 15:30:35 +06:00
# include "qt_unixmanagerfilter.hpp"
2024-03-29 08:23:55 -04:00
# include "qt_util.hpp"
2022-02-15 02:34:13 +06:00
2021-11-25 10:20:56 +01:00
// Void Cast
2022-11-19 08:49:04 -05:00
# define VC(x) const_cast<wchar_t *>(x)
2021-11-25 10:20:56 +01:00
extern QElapsedTimer elapsed_timer ;
2022-11-19 08:49:04 -05:00
extern MainWindow * main_window ;
2021-11-25 10:20:56 +01:00
extern " C " {
2024-12-31 00:48:50 +01:00
# include <86box/keyboard.h>
2021-12-19 23:49:47 +02:00
# include <86box/timer.h>
# include <86box/nvr.h>
2022-11-19 08:49:04 -05:00
extern int qt_nvr_save ( void ) ;
2021-11-25 10:20:56 +01:00
}
2022-01-13 00:48:52 +02:00
void qt_set_sequence_auto_mnemonic ( bool b ) ;
2024-12-31 00:48:50 +01:00
# ifdef Q_OS_WINDOWS
static void
keyboard_getkeymap ( )
{
const LPCSTR keyName = " SYSTEM \\ CurrentControlSet \\ Control \\ Keyboard Layout " ;
const LPCSTR valueName = " Scancode Map " ;
unsigned char buf [ 32768 ] ;
DWORD bufSize ;
HKEY hKey ;
int j ;
UINT32 * bufEx2 ;
int scMapCount ;
UINT16 * bufEx ;
int scancode_unmapped ;
int scancode_mapped ;
/* First, prepare the default scan code map list which is 1:1.
* Remappings will be inserted directly into it .
* 512 bytes so this takes less memory , bit 9 set means E0
* prefix .
*/
for ( j = 0 ; j < 512 ; j + + )
scancode_map [ j ] = j ;
/* Get the scan code remappings from:
HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Keyboard Layout */
bufSize = 32768 ;
if ( RegOpenKeyExA ( HKEY_LOCAL_MACHINE , keyName , 0 , 1 , & hKey ) = = ERROR_SUCCESS ) {
if ( RegQueryValueExA ( hKey , valueName , NULL , NULL , buf , & bufSize ) = = ERROR_SUCCESS ) {
bufEx2 = ( UINT32 * ) buf ;
scMapCount = bufEx2 [ 2 ] ;
if ( ( bufSize ! = 0 ) & & ( scMapCount ! = 0 ) ) {
bufEx = ( UINT16 * ) ( buf + 12 ) ;
for ( j = 0 ; j < scMapCount * 2 ; j + = 2 ) {
/* Each scan code is 32-bit: 16 bits of remapped scan code,
and 16 bits of original scan code . */
scancode_unmapped = bufEx [ j + 1 ] ;
scancode_mapped = bufEx [ j ] ;
scancode_unmapped = convert_scan_code ( scancode_unmapped ) ;
scancode_mapped = convert_scan_code ( scancode_mapped ) ;
/* Ignore source scan codes with prefixes other than E1
that are not E1 1 D . */
if ( scancode_unmapped ! = 0xFFFF )
scancode_map [ scancode_unmapped ] = scancode_mapped ;
}
}
}
RegCloseKey ( hKey ) ;
}
}
2024-12-31 03:59:38 +01:00
static LRESULT CALLBACK
emu_LowLevelKeyboardProc ( int nCode , WPARAM wParam , LPARAM lParam )
{
LPKBDLLHOOKSTRUCT lpKdhs = ( LPKBDLLHOOKSTRUCT ) lParam ;
/* Checks if CTRL was pressed. */
BOOL bCtrlDown = GetAsyncKeyState ( VK_CONTROL ) > > ( ( sizeof ( SHORT ) * 8 ) - 1 ) ;
2025-01-03 00:15:28 +01:00
BOOL is_over_window = ( GetForegroundWindow ( ) = = ( ( HWND ) main_window - > winId ( ) ) ) ;
2024-12-31 03:59:38 +01:00
2025-01-03 00:15:28 +01:00
if ( show_second_monitors ) for ( int monitor_index = 1 ; monitor_index < MONITORS_NUM ; monitor_index + + ) {
const auto & secondaryRenderer = main_window - > renderers [ monitor_index ] ;
2025-01-03 00:47:35 +01:00
is_over_window = is_over_window & & ( secondaryRenderer ! = nullptr ) & &
( GetForegroundWindow ( ) = = ( ( HWND ) secondaryRenderer - > winId ( ) ) ) ;
2025-01-03 00:15:28 +01:00
}
2025-01-02 02:09:15 +01:00
2025-01-03 00:15:28 +01:00
if ( ( nCode < 0 ) | | ( nCode ! = HC_ACTION ) /* || (!mouse_capture && !video_fullscreen)*/ | | ! is_over_window )
2024-12-31 03:59:38 +01:00
return CallNextHookEx ( NULL , nCode , wParam , lParam ) ;
else if ( ( lpKdhs - > scanCode = = 0x01 ) & & ( lpKdhs - > flags & LLKHF_ALTDOWN ) & &
2025-01-02 02:09:15 +01:00
! ( lpKdhs - > flags & ( LLKHF_UP | LLKHF_EXTENDED ) ) )
2024-12-31 00:48:50 +01:00
return TRUE ;
2025-01-02 02:09:15 +01:00
else if ( ( lpKdhs - > scanCode = = 0x01 ) & & bCtrlDown & & ! ( lpKdhs - > flags & ( LLKHF_UP | LLKHF_EXTENDED ) ) )
2024-12-31 00:48:50 +01:00
return TRUE ;
2025-01-02 02:09:15 +01:00
else if ( ( lpKdhs - > scanCode = = 0x0f ) & & ( lpKdhs - > flags & LLKHF_ALTDOWN ) & &
! ( lpKdhs - > flags & ( LLKHF_UP | LLKHF_EXTENDED ) ) )
2024-12-31 00:48:50 +01:00
return TRUE ;
2025-01-02 02:09:15 +01:00
else if ( ( lpKdhs - > scanCode = = 0x0f ) & & bCtrlDown & & ! ( lpKdhs - > flags & ( LLKHF_UP | LLKHF_EXTENDED ) ) )
2024-12-31 00:48:50 +01:00
return TRUE ;
2025-01-02 02:09:15 +01:00
else if ( ( lpKdhs - > scanCode = = 0x39 ) & & ( lpKdhs - > flags & LLKHF_ALTDOWN ) & &
! ( lpKdhs - > flags & ( LLKHF_UP | LLKHF_EXTENDED ) ) )
2024-12-31 00:48:50 +01:00
return TRUE ;
2025-01-02 02:09:15 +01:00
else if ( ( lpKdhs - > scanCode = = 0x3e ) & & ( lpKdhs - > flags & LLKHF_ALTDOWN ) & &
! ( lpKdhs - > flags & ( LLKHF_UP | LLKHF_EXTENDED ) ) )
2024-12-31 00:48:50 +01:00
return TRUE ;
2025-01-02 02:09:15 +01:00
else if ( ( lpKdhs - > scanCode = = 0x49 ) & & bCtrlDown & & ! ( lpKdhs - > flags & LLKHF_UP ) )
2024-12-31 00:48:50 +01:00
return TRUE ;
2025-01-02 02:09:15 +01:00
else if ( ( lpKdhs - > scanCode > = 0x5b ) & & ( lpKdhs - > scanCode < = 0x5d ) & & ( lpKdhs - > flags & LLKHF_EXTENDED ) )
2024-12-31 00:48:50 +01:00
return TRUE ;
2025-01-02 02:09:15 +01:00
else
2024-12-31 00:48:50 +01:00
return CallNextHookEx ( NULL , nCode , wParam , lParam ) ;
}
# endif
2024-12-31 03:59:38 +01:00
# ifdef Q_OS_WINDOWS
static HHOOK llhook = NULL ;
# endif
2021-11-25 10:20:56 +01:00
void
main_thread_fn ( )
{
2023-05-29 01:30:51 -04:00
int frames ;
2021-11-25 10:20:56 +01:00
QThread : : currentThread ( ) - > setPriority ( QThread : : HighestPriority ) ;
2024-05-03 17:02:13 +02:00
plat_set_thread_name ( nullptr , " main_thread_fn " ) ;
2021-11-25 10:20:56 +01:00
framecountx = 0 ;
2022-11-19 08:49:04 -05:00
// title_update = 1;
2024-05-03 17:02:13 +02:00
uint64_t old_time = elapsed_timer . elapsed ( ) ;
int drawits = frames = 0 ;
2021-11-25 10:20:56 +01:00
while ( ! is_quit & & cpu_thread_run ) {
/* See if it is time to run a frame of code. */
2024-05-03 17:02:13 +02:00
const uint64_t new_time = elapsed_timer . elapsed ( ) ;
2022-03-16 00:33:01 -03:00
# ifdef USE_GDBSTUB
if ( gdbstub_next_asap & & ( drawits < = 0 ) )
2022-11-19 08:49:04 -05:00
drawits = 10 ;
2022-03-16 00:33:01 -03:00
else
# endif
2024-05-03 17:02:13 +02:00
drawits + = static_cast < int > ( new_time - old_time ) ;
2021-11-25 10:20:56 +01:00
old_time = new_time ;
if ( drawits > 0 & & ! dopause ) {
/* Yes, so do one frame now. */
drawits - = 10 ;
if ( drawits > 50 )
drawits = 0 ;
2022-08-06 14:23:11 +02:00
# ifdef USE_INSTRUMENT
uint64_t start_time = elapsed_timer . nsecsElapsed ( ) ;
# endif
2021-11-25 10:20:56 +01:00
/* Run a block of code. */
pc_run ( ) ;
2022-08-06 14:23:11 +02:00
# ifdef USE_INSTRUMENT
if ( instru_enabled ) {
2022-11-19 08:49:04 -05:00
uint64_t elapsed_us = ( elapsed_timer . nsecsElapsed ( ) - start_time ) / 1000 ;
uint64_t total_elapsed_ms = ( uint64_t ) ( ( double ) tsc / cpu_s - > rspeed * 1000 ) ;
2022-08-06 14:51:42 +02:00
printf ( " [instrument] %llu, %llu \n " , total_elapsed_ms , elapsed_us ) ;
if ( instru_run_ms & & total_elapsed_ms > = instru_run_ms )
2022-08-06 14:23:11 +02:00
break ;
}
# endif
2021-11-25 10:20:56 +01:00
/* Every 200 frames we save the machine status. */
if ( + + frames > = 200 & & nvr_dosave ) {
qt_nvr_save ( ) ;
nvr_dosave = 0 ;
2022-11-19 08:49:04 -05:00
frames = 0 ;
2021-11-25 10:20:56 +01:00
}
2021-12-13 18:02:22 +02:00
} else {
/* Just so we dont overload the host OS. */
2024-08-24 04:24:06 +02:00
/* Trigger a hard reset if one is pending. */
if ( hard_reset_pending ) {
hard_reset_pending = 0 ;
pc_reset_hard_close ( ) ;
pc_reset_hard_init ( ) ;
}
2023-10-31 00:44:04 +01:00
if ( dopause )
ack_pause ( ) ;
2024-08-24 04:24:06 +02:00
2024-12-24 19:25:00 +01:00
plat_delay_ms ( 1 ) ;
2021-12-13 18:02:22 +02:00
}
2021-11-25 10:20:56 +01:00
}
is_quit = 1 ;
2024-06-29 19:43:42 -04:00
for ( uint8_t i = 1 ; i < GFXCARD_MAX ; i + + ) {
if ( gfxcard [ i ] ) {
ui_deinit_monitor ( i ) ;
2024-12-24 19:30:35 +01:00
plat_delay_ms ( 500 ) ;
2024-06-29 19:43:42 -04:00
}
2023-03-04 23:10:26 +06:00
}
QTimer : : singleShot ( 0 , QApplication : : instance ( ) , [ ] ( ) { QApplication : : processEvents ( ) ; QApplication : : instance ( ) - > quit ( ) ; } ) ;
2021-11-25 10:20:56 +01:00
}
2022-11-19 08:49:04 -05:00
static std : : thread * main_thread ;
2022-07-04 01:50:42 +06:00
2022-11-19 08:49:04 -05:00
int
main ( int argc , char * argv [ ] )
{
2022-02-09 16:45:57 +06:00
# if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
2022-02-09 20:57:58 +06:00
QApplication : : setAttribute ( Qt : : AA_DisableHighDpiScaling , false ) ;
2022-02-09 20:49:11 +06:00
QApplication : : setAttribute ( Qt : : AA_UseHighDpiPixmaps ) ;
QApplication : : setAttribute ( Qt : : AA_EnableHighDpiScaling ) ;
2022-02-09 16:45:57 +06:00
# endif
2022-02-11 13:49:45 +06:00
# if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
2022-02-10 12:59:33 +06:00
QApplication : : setHighDpiScaleFactorRoundingPolicy ( Qt : : HighDpiScaleFactorRoundingPolicy : : PassThrough ) ;
2022-02-11 13:49:45 +06:00
# endif
2024-12-31 00:48:50 +01:00
2022-02-09 20:49:11 +06:00
QApplication app ( argc , argv ) ;
2022-02-11 16:24:49 +06:00
QLocale : : setDefault ( QLocale : : C ) ;
2022-02-12 20:15:21 +06:00
2022-01-13 00:48:52 +02:00
qt_set_sequence_auto_mnemonic ( false ) ;
2021-12-31 12:36:55 +06:00
Q_INIT_RESOURCE ( qt_resources ) ;
Q_INIT_RESOURCE ( qt_translations ) ;
2021-12-25 15:34:00 +06:00
QSurfaceFormat fmt = QSurfaceFormat : : defaultFormat ( ) ;
fmt . setSwapInterval ( 0 ) ;
QSurfaceFormat : : setDefaultFormat ( fmt ) ;
2021-12-12 18:19:44 +02:00
app . setStyle ( new StyleOverride ( ) ) ;
2022-01-08 16:39:51 +06:00
2021-11-30 16:26:49 +06:00
# ifdef __APPLE__
CocoaEventFilter cocoafilter ;
app . installNativeEventFilter ( & cocoafilter ) ;
# endif
2021-11-25 10:20:56 +01:00
elapsed_timer . start ( ) ;
2024-12-31 00:48:50 +01:00
for ( size_t i = 0 ; i < sizeof ( scancode_map ) / sizeof ( scancode_map [ 0 ] ) ; i + + )
scancode_map [ i ] = i ;
# ifdef Q_OS_WINDOWS
keyboard_getkeymap ( ) ;
# endif
2022-11-19 08:49:04 -05:00
if ( ! pc_init ( argc , argv ) ) {
2021-12-24 15:02:16 +06:00
return 0 ;
}
2022-03-11 12:03:54 +06:00
2022-08-14 12:28:36 +06:00
bool startMaximized = window_remember & & monitor_settings [ 0 ] . mon_window_maximized ;
2022-03-11 12:03:54 +06:00
fprintf ( stderr , " Qt: version %s, platform \" %s \" \n " , qVersion ( ) , QApplication : : platformName ( ) . toUtf8 ( ) . data ( ) ) ;
2022-01-08 16:39:51 +06:00
ProgSettings : : loadTranslators ( & app ) ;
2022-02-12 20:15:21 +06:00
# ifdef Q_OS_WINDOWS
2024-03-20 16:48:09 +05:00
QApplication : : setFont ( QFont ( ProgSettings : : getFontName ( lang_id ) , 9 ) ) ;
2022-02-13 00:35:46 +06:00
SetCurrentProcessExplicitAppUserModelID ( L " 86Box.86Box " ) ;
2022-02-12 20:15:21 +06:00
# endif
2023-12-20 15:28:32 +05:00
2023-12-31 00:09:50 -03:00
# ifndef Q_OS_MACOS
2023-12-31 05:23:17 +05:00
# ifdef RELEASE_BUILD
2024-03-15 18:16:21 +01:00
app . setWindowIcon ( QIcon ( " :/settings/qt/icons/86Box-green.ico " ) ) ;
2023-12-31 05:23:17 +05:00
# elif defined ALPHA_BUILD
2024-03-15 18:16:21 +01:00
app . setWindowIcon ( QIcon ( " :/settings/qt/icons/86Box-red.ico " ) ) ;
2023-12-31 05:23:17 +05:00
# elif defined BETA_BUILD
2024-03-15 18:16:21 +01:00
app . setWindowIcon ( QIcon ( " :/settings/qt/icons/86Box-yellow.ico " ) ) ;
2023-12-31 05:23:17 +05:00
# else
2024-03-15 18:16:21 +01:00
app . setWindowIcon ( QIcon ( " :/settings/qt/icons/86Box-gray.ico " ) ) ;
2023-12-31 01:44:31 +01:00
# endif
2023-12-20 15:28:32 +05:00
2023-12-31 05:23:17 +05:00
# ifdef Q_OS_UNIX
2023-12-20 20:15:31 +05:00
app . setDesktopFileName ( " net.86box.86Box " ) ;
2023-12-31 05:23:17 +05:00
# endif
2023-12-20 20:15:31 +05:00
# endif
2022-11-19 08:49:04 -05:00
if ( ! pc_init_modules ( ) ) {
2024-03-19 14:27:19 +05:00
QMessageBox fatalbox ( QMessageBox : : Icon : : Critical , QObject : : tr ( " No ROMs found " ) ,
QObject : : tr ( " 86Box could not find any usable ROM images. \n \n Please <a href= \" https://github.com/86Box/roms/releases/latest \" >download</a> a ROM set and extract it into the \" roms \" directory. " ) ,
QMessageBox : : Ok ) ;
fatalbox . setTextFormat ( Qt : : TextFormat : : RichText ) ;
fatalbox . exec ( ) ;
2021-12-06 21:24:53 +01:00
return 6 ;
}
2021-11-25 10:20:56 +01:00
2024-03-29 08:23:55 -04:00
// UUID / copy / move detection
if ( ! util : : compareUuid ( ) ) {
QMessageBox movewarnbox ;
movewarnbox . setIcon ( QMessageBox : : Icon : : Warning ) ;
2024-05-24 11:50:01 +03:00
movewarnbox . setText ( QObject : : tr ( " This machine might have been moved or copied. " ) ) ;
movewarnbox . setInformativeText ( QObject : : tr ( " In order to ensure proper networking functionality, 86Box needs to know if this machine was moved or copied. \n \n Select \" I Copied It \" if you are not sure. " ) ) ;
2024-03-29 08:23:55 -04:00
const QPushButton * movedButton = movewarnbox . addButton ( QObject : : tr ( " I Moved It " ) , QMessageBox : : AcceptRole ) ;
const QPushButton * copiedButton = movewarnbox . addButton ( QObject : : tr ( " I Copied It " ) , QMessageBox : : DestructiveRole ) ;
QPushButton * cancelButton = movewarnbox . addButton ( QObject : : tr ( " Cancel " ) , QMessageBox : : RejectRole ) ;
movewarnbox . setDefaultButton ( cancelButton ) ;
movewarnbox . exec ( ) ;
if ( movewarnbox . clickedButton ( ) = = copiedButton ) {
util : : storeCurrentUuid ( ) ;
util : : generateNewMacAdresses ( ) ;
} else if ( movewarnbox . clickedButton ( ) = = movedButton ) {
util : : storeCurrentUuid ( ) ;
}
}
2024-03-10 18:01:09 -03:00
# ifdef Q_OS_WINDOWS
# if !defined(EMU_BUILD_NUM) || (EMU_BUILD_NUM != 5624)
2024-06-16 14:16:53 +06:00
HWND winbox = FindWindowW ( L " TWinBoxMain " , NULL ) ;
2024-03-10 18:01:09 -03:00
if ( winbox & &
2024-06-16 14:16:53 +06:00
FindWindowExW ( winbox , NULL , L " TToolBar " , NULL ) & &
FindWindowExW ( winbox , NULL , L " TListBox " , NULL ) & &
FindWindowExW ( winbox , NULL , L " TStatusBar " , NULL ) & &
( winbox = FindWindowExW ( winbox , NULL , L " TPageControl " , NULL ) ) & & /* holds a TTabSheet even on VM pages */
FindWindowExW ( winbox , NULL , L " TTabSheet " , NULL ) )
2024-03-10 18:01:09 -03:00
# endif
{
QMessageBox warningbox ( QMessageBox : : Icon : : Warning , QObject : : tr ( " WinBox is no longer supported " ) ,
QObject : : tr ( " Development of the WinBox manager stopped in 2022 due to a lack of maintainers. As we direct our efforts towards making 86Box even better, we have made the decision to no longer support WinBox as a manager. \n \n No further updates will be provided through WinBox, and you may encounter incorrect behavior should you continue using it with newer versions of 86Box. Any bug reports related to WinBox behavior will be closed as invalid. \n \n Go to 86box.net for a list of other managers you can use. " ) ,
QMessageBox : : NoButton ) ;
warningbox . addButton ( QObject : : tr ( " Continue " ) , QMessageBox : : AcceptRole ) ;
warningbox . addButton ( QObject : : tr ( " Exit " ) , QMessageBox : : RejectRole ) ;
warningbox . exec ( ) ;
if ( warningbox . result ( ) = = QDialog : : Accepted )
return 0 ;
}
# endif
2022-11-19 08:49:04 -05:00
if ( settings_only ) {
2022-02-06 12:45:55 +06:00
Settings settings ;
2022-11-19 08:49:04 -05:00
if ( settings . exec ( ) = = QDialog : : Accepted ) {
2022-02-06 12:45:55 +06:00
settings . save ( ) ;
config_save ( ) ;
}
return 0 ;
}
2022-02-06 11:48:56 +02:00
2023-11-05 00:53:57 +01:00
/* Warn the user about unsupported configs */
if ( cpu_override ) {
QMessageBox warningbox ( QMessageBox : : Icon : : Warning , QObject : : tr ( " You are loading an unsupported configuration " ) ,
QObject : : tr ( " CPU type filtering based on selected machine is disabled for this emulated machine. \n \n This makes it possible to choose a CPU that is otherwise incompatible with the selected machine. However, you may run into incompatibilities with the machine BIOS or other software. \n \n Enabling this setting is not officially supported and any bug reports filed may be closed as invalid. " ) ,
2023-11-05 02:10:39 +01:00
QMessageBox : : NoButton ) ;
2023-11-05 00:53:57 +01:00
warningbox . addButton ( QObject : : tr ( " Continue " ) , QMessageBox : : AcceptRole ) ;
warningbox . addButton ( QObject : : tr ( " Exit " ) , QMessageBox : : RejectRole ) ;
warningbox . exec ( ) ;
2023-11-05 02:10:39 +01:00
if ( warningbox . result ( ) = = QDialog : : Accepted )
return 0 ;
2023-11-05 00:53:57 +01:00
}
2023-02-01 17:17:56 +01:00
# ifdef DISCORD
2022-02-06 11:48:56 +02:00
discord_load ( ) ;
2023-02-01 17:17:56 +01:00
# endif
2022-02-06 11:48:56 +02:00
2021-11-29 12:25:27 +01:00
main_window = new MainWindow ( ) ;
2022-08-14 12:28:36 +06:00
if ( startMaximized ) {
main_window - > showMaximized ( ) ;
} else {
main_window - > show ( ) ;
}
2021-12-05 15:57:46 +06:00
app . installEventFilter ( main_window ) ;
2021-12-09 20:59:50 +02:00
# ifdef Q_OS_WINDOWS
2022-01-22 01:10:11 +02:00
/* Setup VM-manager messages */
std : : unique_ptr < WindowsManagerFilter > wmfilter ;
2022-11-19 08:49:04 -05:00
if ( source_hwnd ) {
HWND main_hwnd = ( HWND ) main_window - > winId ( ) ;
2022-01-22 02:41:02 +02:00
2022-01-22 01:10:11 +02:00
wmfilter . reset ( new WindowsManagerFilter ( ) ) ;
2022-01-22 12:40:15 +02:00
QObject : : connect ( wmfilter . get ( ) , & WindowsManagerFilter : : showsettings , main_window , & MainWindow : : showSettings ) ;
QObject : : connect ( wmfilter . get ( ) , & WindowsManagerFilter : : pause , main_window , & MainWindow : : togglePause ) ;
QObject : : connect ( wmfilter . get ( ) , & WindowsManagerFilter : : reset , main_window , & MainWindow : : hardReset ) ;
2022-02-12 17:31:28 +02:00
QObject : : connect ( wmfilter . get ( ) , & WindowsManagerFilter : : request_shutdown , main_window , & MainWindow : : close ) ;
2022-11-19 08:49:04 -05:00
QObject : : connect ( wmfilter . get ( ) , & WindowsManagerFilter : : force_shutdown , [ ] ( ) {
2022-02-12 17:31:28 +02:00
do_stop ( ) ;
emit main_window - > close ( ) ;
} ) ;
2022-11-19 08:49:04 -05:00
QObject : : connect ( wmfilter . get ( ) , & WindowsManagerFilter : : ctrlaltdel , [ ] ( ) { pc_send_cad ( ) ; } ) ;
QObject : : connect ( wmfilter . get ( ) , & WindowsManagerFilter : : dialogstatus , [ main_hwnd ] ( bool open ) {
PostMessage ( ( HWND ) ( uintptr_t ) source_hwnd , WM_SENDDLGSTATUS , ( WPARAM ) ( open ? 1 : 0 ) , ( LPARAM ) main_hwnd ) ;
2022-01-22 02:41:02 +02:00
} ) ;
/* Native filter to catch VM-managers commands */
2022-01-22 01:10:11 +02:00
app . installNativeEventFilter ( wmfilter . get ( ) ) ;
2022-01-22 02:41:02 +02:00
/* Filter to catch main window being blocked (by modal dialog) */
main_window - > installEventFilter ( wmfilter . get ( ) ) ;
2022-01-22 01:10:11 +02:00
/* Send main window HWND to manager */
2022-11-19 08:49:04 -05:00
PostMessage ( ( HWND ) ( uintptr_t ) source_hwnd , WM_SENDHWND , ( WPARAM ) unique_id , ( LPARAM ) main_hwnd ) ;
2022-01-22 01:10:11 +02:00
/* Send shutdown message to manager */
2022-11-19 08:49:04 -05:00
QObject : : connect ( & app , & QApplication : : destroyed , [ main_hwnd ] ( QObject * ) {
PostMessage ( ( HWND ) ( uintptr_t ) source_hwnd , WM_HAS_SHUTDOWN , ( WPARAM ) 0 , ( LPARAM ) main_hwnd ) ;
2022-01-22 01:10:11 +02:00
} ) ;
}
2025-01-02 02:09:15 +01:00
/* Force raw input if a debugger is present. */
if ( IsDebuggerPresent ( ) ) {
pclog ( " WARNING: Debugged detected, forcing raw input \n " ) ;
2025-01-03 00:15:28 +01:00
hook_enabled = 0 ;
2025-01-02 02:09:15 +01:00
}
2022-01-22 01:10:11 +02:00
/* Setup raw input */
2021-12-12 17:52:43 +02:00
auto rawInputFilter = WindowsRawInputFilter : : Register ( main_window ) ;
2022-11-19 08:49:04 -05:00
if ( rawInputFilter ) {
2021-12-09 20:59:50 +02:00
app . installNativeEventFilter ( rawInputFilter . get ( ) ) ;
2025-01-02 02:09:15 +01:00
main_window - > setSendKeyboardInput ( false ) ;
2022-02-20 02:26:27 -05:00
}
2021-12-09 20:59:50 +02:00
# endif
2022-02-27 15:30:35 +06:00
UnixManagerSocket socket ;
2022-11-19 08:49:04 -05:00
if ( qgetenv ( " 86BOX_MANAGER_SOCKET " ) . size ( ) ) {
2022-02-28 12:16:43 +06:00
QObject : : connect ( & socket , & UnixManagerSocket : : showsettings , main_window , & MainWindow : : showSettings ) ;
QObject : : connect ( & socket , & UnixManagerSocket : : pause , main_window , & MainWindow : : togglePause ) ;
2022-03-06 18:00:23 +02:00
QObject : : connect ( & socket , & UnixManagerSocket : : resetVM , main_window , & MainWindow : : hardReset ) ;
2022-02-28 12:16:43 +06:00
QObject : : connect ( & socket , & UnixManagerSocket : : request_shutdown , main_window , & MainWindow : : close ) ;
2022-11-19 08:49:04 -05:00
QObject : : connect ( & socket , & UnixManagerSocket : : force_shutdown , [ ] ( ) {
2022-02-28 12:16:43 +06:00
do_stop ( ) ;
emit main_window - > close ( ) ;
} ) ;
2022-11-19 08:49:04 -05:00
QObject : : connect ( & socket , & UnixManagerSocket : : ctrlaltdel , [ ] ( ) { pc_send_cad ( ) ; } ) ;
2022-02-28 12:16:43 +06:00
main_window - > installEventFilter ( & socket ) ;
2022-02-27 15:30:35 +06:00
socket . connectToServer ( qgetenv ( " 86BOX_MANAGER_SOCKET " ) ) ;
}
2023-10-06 01:18:16 +05:00
2022-11-19 08:49:04 -05:00
// pc_reset_hard_init();
2021-11-25 10:20:56 +01:00
2021-12-06 21:33:25 +01:00
QTimer onesec ;
QObject : : connect ( & onesec , & QTimer : : timeout , & app , [ ] {
pc_onesec ( ) ;
} ) ;
2022-02-06 14:41:25 +06:00
onesec . setTimerType ( Qt : : PreciseTimer ) ;
2021-12-06 21:33:25 +01:00
onesec . start ( 1000 ) ;
2023-02-01 17:17:56 +01:00
# ifdef DISCORD
QTimer discordupdate ;
2022-01-09 01:04:59 +06:00
if ( discord_loaded ) {
QTimer : : singleShot ( 1000 , & app , [ ] {
if ( enable_discord ) {
discord_init ( ) ;
discord_update_activity ( dopause ) ;
} else
discord_close ( ) ;
} ) ;
QObject : : connect ( & discordupdate , & QTimer : : timeout , & app , [ ] {
discord_run_callbacks ( ) ;
} ) ;
2022-09-01 13:49:35 -04:00
discordupdate . start ( 1000 ) ;
2022-01-09 01:04:59 +06:00
}
2023-02-01 17:17:56 +01:00
# endif
2021-11-25 10:20:56 +01:00
/* Initialize the rendering window, or fullscreen. */
2022-11-19 08:49:04 -05:00
QTimer : : singleShot ( 0 , & app , [ ] {
2022-07-04 01:50:42 +06:00
pc_reset_hard_init ( ) ;
main_thread = new std : : thread ( main_thread_fn ) ;
2023-12-11 20:32:51 +01:00
/* Set the PAUSE mode depending on the renderer. */
# ifdef USE_VNC
2024-11-13 06:31:16 +01:00
if ( vid_api = = 5 )
2023-12-11 20:32:51 +01:00
plat_pause ( 1 ) ;
else
# endif
plat_pause ( 0 ) ;
2021-11-25 10:20:56 +01:00
} ) ;
2024-12-31 03:59:38 +01:00
# ifdef Q_OS_WINDOWS
2025-01-03 00:15:28 +01:00
if ( hook_enabled ) {
/* Yes, low-level hooks *DO* work raw input, at least global ones. */
2024-12-31 03:59:38 +01:00
llhook = SetWindowsHookEx ( WH_KEYBOARD_LL , emu_LowLevelKeyboardProc , NULL , 0 ) ;
atexit ( [ ] ( ) - > void {
if ( llhook )
UnhookWindowsHookEx ( llhook ) ;
} ) ;
}
# endif
2024-05-03 17:02:13 +02:00
const auto ret = app . exec ( ) ;
2021-11-25 10:20:56 +01:00
cpu_thread_run = 0 ;
2022-07-04 01:50:42 +06:00
main_thread - > join ( ) ;
2022-07-05 16:40:04 +06:00
pc_close ( nullptr ) ;
2022-08-01 13:26:07 +06:00
endblit ( ) ;
2021-11-25 10:20:56 +01:00
2022-02-27 15:30:35 +06:00
socket . close ( ) ;
2021-11-25 10:20:56 +01:00
return ret ;
}