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
* Common platform functions .
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 <cstdio>
# include <mutex>
2021-12-08 11:05:52 +01:00
# include <thread>
2021-11-25 10:20:56 +01:00
# include <memory>
# include <algorithm>
2021-12-31 12:36:55 +06:00
# include <map>
2021-11-25 10:20:56 +01:00
# include <QDebug>
# include <QDir>
# include <QFileInfo>
# include <QTemporaryFile>
2022-04-08 00:58:38 +02:00
# include <QStandardPaths>
2021-11-25 10:20:56 +01:00
# include <QCoreApplication>
2021-12-24 11:53:24 +06:00
# include <QDateTime>
2022-02-27 15:30:35 +06:00
# include <QLocalSocket>
2022-05-05 11:55:17 +06:00
# include <QTimer>
2021-11-25 10:20:56 +01:00
# include <QLibrary>
# include <QElapsedTimer>
2022-07-11 03:44:30 +02:00
# include "qt_rendererstack.hpp"
2021-12-24 12:59:10 +06:00
# include "qt_mainwindow.hpp"
2022-01-08 16:39:51 +06:00
# include "qt_progsettings.hpp"
2021-12-24 12:59:10 +06:00
2021-11-25 10:20:56 +01:00
# ifdef Q_OS_UNIX
2022-11-19 08:49:04 -05:00
# include <sys / mman.h>
2021-11-25 10:20:56 +01:00
# endif
2023-05-29 01:30:51 -04:00
#if 0
static QByteArray buf ;
# endif
2021-11-25 10:20:56 +01:00
extern QElapsedTimer elapsed_timer ;
2022-11-19 08:49:04 -05:00
extern MainWindow * main_window ;
QElapsedTimer elapsed_timer ;
2021-12-08 11:05:52 +01:00
2022-11-19 08:49:04 -05:00
static std : : atomic_int blitmx_contention = 0 ;
2022-07-04 01:50:42 +06:00
static std : : recursive_mutex blitmx ;
2021-11-25 10:20:56 +01:00
class CharPointer {
public :
2022-11-19 08:49:04 -05:00
CharPointer ( char * buf , int size )
: b ( buf )
, s ( size )
{
}
CharPointer & operator = ( const QByteArray & ba )
{
2021-11-25 10:20:56 +01:00
if ( s > 0 ) {
2022-11-19 08:49:04 -05:00
strncpy ( b , ba . data ( ) , s - 1 ) ;
2021-11-25 10:20:56 +01:00
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 ;
}
2022-11-19 08:49:04 -05:00
2021-11-25 10:20:56 +01:00
private :
2022-11-19 08:49:04 -05:00
char * b ;
int s ;
2021-11-25 10:20:56 +01:00
} ;
extern " C " {
2021-12-02 19:35:08 +02:00
# ifdef Q_OS_WINDOWS
2022-03-07 21:47:48 +02:00
# ifndef NOMINMAX
# define NOMINMAX
# endif
# include <windows.h>
# include <86box / win.h>
2021-12-24 14:16:10 +06:00
# else
2022-03-07 21:47:48 +02:00
# include <strings.h>
2021-12-02 19:35:08 +02:00
# endif
2021-11-25 10:20:56 +01:00
# include <86box/86box.h>
# include <86box/device.h>
# include <86box/gameport.h>
2021-12-23 01:56:56 +06:00
# include <86box/timer.h>
# include <86box/nvr.h>
2022-04-19 23:06:39 +02:00
# include <86box/path.h>
2021-11-25 10:20:56 +01:00
# include <86box/plat_dynld.h>
2022-04-06 16:16:25 +06:00
# include <86box/mem.h>
# include <86box/rom.h>
2021-11-25 10:20:56 +01:00
# include <86box/config.h>
# include <86box/ui.h>
2023-02-01 17:17:56 +01:00
# ifdef DISCORD
# include <86box / discord.h>
# endif
2021-11-25 10:20:56 +01:00
# include "../cpu/cpu.h"
# include <86box/plat.h>
2022-11-19 08:49:04 -05:00
volatile int cpu_thread_run = 1 ;
int mouse_capture = 0 ;
int fixed_size_x = 640 ;
int fixed_size_y = 480 ;
int rctrl_is_lalt = 0 ;
int update_icons = 1 ;
int kbd_req_capture = 0 ;
int hide_status_bar = 0 ;
int hide_tool_bar = 0 ;
uint32_t lang_id = 0x0409 , lang_sys = 0x0409 ; // Multilangual UI variables, for now all set to LCID of en-US
2021-11-25 10:20:56 +01:00
2022-11-19 08:49:04 -05:00
int
stricmp ( const char * s1 , const char * s2 )
2021-11-25 10:20:56 +01:00
{
2021-12-24 14:16:10 +06:00
# ifdef Q_OS_WINDOWS
return _stricmp ( s1 , s2 ) ;
# else
return strcasecmp ( s1 , s2 ) ;
# endif
2021-11-25 10:20:56 +01:00
}
2022-11-19 08:49:04 -05:00
int
strnicmp ( const char * s1 , const char * s2 , size_t n )
2021-11-25 10:20:56 +01:00
{
2021-12-24 14:16:10 +06:00
# ifdef Q_OS_WINDOWS
return _strnicmp ( s1 , s2 , n ) ;
# else
return strncasecmp ( s1 , s2 , n ) ;
# endif
2021-11-25 10:20:56 +01:00
}
void
do_stop ( void )
{
2022-02-02 22:08:19 +06:00
cpu_thread_run = 0 ;
2023-05-29 01:30:51 -04:00
#if 0
main_window - > close ( ) ;
# endif
2021-11-25 10:20:56 +01:00
}
2022-11-19 08:49:04 -05:00
void
plat_get_exe_name ( char * s , int size )
2021-11-25 10:20:56 +01:00
{
2021-12-02 19:35:08 +02:00
QByteArray exepath_temp = QCoreApplication : : applicationDirPath ( ) . toLocal8Bit ( ) ;
2022-11-19 08:49:04 -05:00
memcpy ( s , exepath_temp . data ( ) , std : : min ( ( qsizetype ) exepath_temp . size ( ) , ( qsizetype ) size ) ) ;
2021-12-02 19:35:08 +02:00
2022-04-19 23:06:39 +02:00
path_slash ( s ) ;
2021-11-25 10:20:56 +01:00
}
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 )
{
2022-10-01 17:39:03 -04:00
# if defined(Q_OS_MACOS) or defined(Q_OS_LINUX)
QFileInfo fi ( path ) ;
2022-11-19 08:49:04 -05:00
QString filename = ( fi . isRelative ( ) & & ! fi . filePath ( ) . isEmpty ( ) ) ? usr_path + fi . filePath ( ) : fi . filePath ( ) ;
2022-10-01 17:39:03 -04:00
return fopen ( filename . toUtf8 ( ) . constData ( ) , mode ) ;
# else
2022-01-15 00:07:01 +02:00
return fopen ( QString : : fromUtf8 ( path ) . toLocal8Bit ( ) , mode ) ;
2022-10-01 17:39:03 -04:00
# endif
2021-11-25 10:20:56 +01:00
}
FILE *
plat_fopen64 ( const char * path , const char * mode )
{
2022-08-30 19:38:22 -04:00
# if defined(Q_OS_MACOS) or defined(Q_OS_LINUX)
2022-08-30 17:18:51 -04:00
QFileInfo fi ( path ) ;
2022-11-19 08:49:04 -05:00
QString filename = ( fi . isRelative ( ) & & ! fi . filePath ( ) . isEmpty ( ) ) ? usr_path + fi . filePath ( ) : fi . filePath ( ) ;
2022-08-30 17:18:51 -04:00
return fopen ( filename . toUtf8 ( ) . constData ( ) , mode ) ;
# else
2022-08-11 01:16:56 +06:00
return fopen ( QString : : fromUtf8 ( path ) . toLocal8Bit ( ) , mode ) ;
2022-08-30 17:18:51 -04:00
# endif
2021-11-25 10:20:56 +01:00
}
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 )
{
2022-04-20 13:35:14 -03:00
# ifdef __APPLE__
/* Working directory for .app bundles is undefined. */
strncpy ( bufp , exe_path , max ) ;
# else
2021-11-25 10:20:56 +01:00
CharPointer ( bufp , max ) = QDir : : currentPath ( ) . toUtf8 ( ) ;
2022-04-20 13:35:14 -03:00
# endif
2021-11-25 10:20:56 +01:00
return 0 ;
}
void
2022-04-19 23:06:39 +02:00
path_get_dirname ( char * dest , const char * path )
2021-11-25 10:20:56 +01:00
{
QFileInfo fi ( path ) ;
CharPointer ( dest , - 1 ) = fi . dir ( ) . path ( ) . toUtf8 ( ) ;
}
char *
2022-04-19 23:06:39 +02:00
path_get_extension ( char * s )
2021-11-25 10:20:56 +01:00
{
auto len = strlen ( s ) ;
auto idx = QByteArray : : fromRawData ( s , len ) . lastIndexOf ( ' . ' ) ;
if ( idx > = 0 ) {
2022-11-19 08:49:04 -05:00
return s + idx + 1 ;
2021-11-25 10:20:56 +01:00
}
2022-11-19 08:49:04 -05:00
return s + len ;
2021-11-25 10:20:56 +01:00
}
char *
2022-04-19 23:06:39 +02:00
path_get_filename ( char * s )
2021-11-25 10:20:56 +01:00
{
2021-12-02 19:35:08 +02:00
# ifdef Q_OS_WINDOWS
int c = strlen ( s ) - 1 ;
while ( c > 0 ) {
2022-11-19 08:49:04 -05:00
if ( s [ c ] = = ' / ' | | s [ c ] = = ' \\ ' )
return ( & s [ c + 1 ] ) ;
c - - ;
2021-12-02 19:35:08 +02:00
}
2023-05-29 01:30:51 -04:00
return s ;
2021-12-02 19:35:08 +02:00
# else
2022-11-19 08:49:04 -05:00
auto idx = QByteArray : : fromRawData ( s , strlen ( s ) ) . lastIndexOf ( QDir : : separator ( ) . toLatin1 ( ) ) ;
2021-11-25 10:20:56 +01:00
if ( idx > = 0 ) {
2022-11-19 08:49:04 -05:00
return s + idx + 1 ;
2021-11-25 10:20:56 +01:00
}
return s ;
2021-12-02 19:35:08 +02:00
# endif
2021-11-25 10:20:56 +01:00
}
int
2022-04-19 23:06:39 +02:00
path_abs ( char * path )
2021-11-25 10:20:56 +01:00
{
2022-02-11 00:31:41 +06:00
# ifdef Q_OS_WINDOWS
if ( ( path [ 1 ] = = ' : ' ) | | ( path [ 0 ] = = ' \\ ' ) | | ( path [ 0 ] = = ' / ' ) )
return 1 ;
return 0 ;
# else
return path [ 0 ] = = ' / ' ;
# endif
2021-11-25 10:20:56 +01:00
}
2022-03-04 01:17:38 +06:00
void
2022-11-19 08:49:04 -05:00
path_normalize ( char * path )
2022-03-04 01:17:38 +06:00
{
2022-03-04 14:00:24 +06:00
# ifdef Q_OS_WINDOWS
2022-11-19 08:49:04 -05:00
while ( * path + + ! = 0 ) {
if ( * path = = ' \\ ' )
* path = ' / ' ;
2022-03-04 01:17:38 +06:00
}
2022-03-04 14:00:24 +06:00
# endif
2022-03-04 01:17:38 +06:00
}
2021-11-25 10:20:56 +01:00
void
2022-04-19 23:06:39 +02:00
path_slash ( char * path )
2021-11-25 10:20:56 +01:00
{
2022-11-19 08:49:04 -05:00
auto len = strlen ( path ) ;
2022-03-04 01:17:38 +06:00
auto separator = ' / ' ;
2022-11-19 08:49:04 -05:00
if ( path [ len - 1 ] ! = separator ) {
path [ len ] = separator ;
path [ len + 1 ] = 0 ;
2021-11-25 10:20:56 +01:00
}
2022-04-19 23:06:39 +02:00
path_normalize ( path ) ;
2021-11-25 10:20:56 +01:00
}
void
2022-04-19 23:06:39 +02:00
path_append_filename ( char * dest , const char * s1 , const char * s2 )
2021-11-25 10:20:56 +01:00
{
strcpy ( dest , s1 ) ;
2022-04-19 23:06:39 +02:00
path_slash ( dest ) ;
2021-11-25 10:20:56 +01:00
strcat ( dest , s2 ) ;
}
void
plat_tempfile ( char * bufp , char * prefix , char * suffix )
{
QString name ;
if ( prefix ! = nullptr ) {
name . append ( QString ( " %1- " ) . arg ( prefix ) ) ;
}
2022-11-19 08:49:04 -05:00
name . append ( QDateTime : : currentDateTime ( ) . toString ( " yyyyMMdd-hhmmss-zzzz " ) ) ;
if ( suffix )
name . append ( suffix ) ;
strcpy ( bufp , name . toUtf8 ( ) . data ( ) ) ;
2021-11-25 10:20:56 +01:00
}
2022-11-19 08:49:04 -05:00
void
plat_remove ( char * path )
2021-11-25 10:20:56 +01:00
{
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
2022-11-19 08:49:04 -05:00
# if defined Q_OS_DARWIN && defined MAP_JIT
2022-01-07 15:00:00 +06:00
void * ret = mmap ( 0 , size , PROT_READ | PROT_WRITE | ( executable ? PROT_EXEC : 0 ) , MAP_ANON | MAP_PRIVATE | ( executable ? MAP_JIT : 0 ) , - 1 , 0 ) ;
2022-11-19 08:49:04 -05:00
# else
2022-01-07 15:00:00 +06:00
void * ret = mmap ( 0 , size , PROT_READ | PROT_WRITE | ( executable ? PROT_EXEC : 0 ) , MAP_ANON | MAP_PRIVATE , - 1 , 0 ) ;
2022-11-19 08:49:04 -05:00
# endif
2021-12-26 15:48:06 +06:00
return ( ret = = MAP_FAILED ) ? nullptr : ret ;
2021-11-25 10:20:56 +01:00
# endif
}
void
plat_munmap ( void * ptr , size_t size )
{
2021-12-02 19:35:08 +02:00
# if defined Q_OS_WINDOWS
VirtualFree ( ptr , 0 , MEM_RELEASE ) ;
# else
2021-11-25 10:20:56 +01:00
munmap ( ptr , size ) ;
2021-12-02 19:35:08 +02:00
# endif
2021-11-25 10:20:56 +01:00
}
void
plat_pause ( int p )
{
static wchar_t oldtitle [ 512 ] ;
2023-05-29 01:30:51 -04:00
wchar_t title [ 1024 ] ;
wchar_t paused_msg [ 512 ] ;
2021-11-25 10:20:56 +01:00
2022-02-13 19:28:28 +06:00
if ( p = = dopause ) {
# ifdef Q_OS_WINDOWS
if ( source_hwnd )
2022-11-19 08:49:04 -05:00
PostMessage ( ( HWND ) ( uintptr_t ) source_hwnd , WM_SENDSTATUS , ( WPARAM ) ! ! p , ( LPARAM ) ( HWND ) main_window - > winId ( ) ) ;
2022-02-13 19:28:28 +06:00
# endif
return ;
}
2022-08-02 02:57:00 +02:00
2021-12-23 01:56:56 +06:00
if ( ( p = = 0 ) & & ( time_sync & TIME_SYNC_ENABLED ) )
2022-01-09 01:04:59 +06:00
nvr_time_sync ( ) ;
2021-12-23 01:56:56 +06:00
2021-11-25 10:20:56 +01:00
dopause = p ;
if ( p ) {
2022-11-19 08:49:04 -05:00
if ( mouse_capture )
plat_mouse_capture ( 0 ) ;
2022-08-02 02:57:00 +02:00
2021-11-25 10:20:56 +01:00
wcsncpy ( oldtitle , ui_window_title ( NULL ) , sizeof_w ( oldtitle ) - 1 ) ;
2022-02-13 14:42:36 +01:00
wcscpy ( title , oldtitle ) ;
2022-05-24 23:06:28 +02:00
paused_msg [ QObject : : tr ( " - PAUSED " ) . toWCharArray ( paused_msg ) ] = 0 ;
2022-02-13 07:03:37 +05:00
wcscat ( title , paused_msg ) ;
2021-11-25 10:20:56 +01:00
ui_window_title ( title ) ;
} else {
ui_window_title ( oldtitle ) ;
}
2023-02-01 17:17:56 +01:00
# ifdef DISCORD
2022-01-09 01:04:59 +06:00
discord_update_activity ( dopause ) ;
2023-02-01 17:17:56 +01:00
# endif
2022-10-29 09:09:30 -04:00
QTimer : : singleShot ( 0 , main_window , & MainWindow : : updateUiPauseState ) ;
2022-01-22 01:10:11 +02:00
# ifdef Q_OS_WINDOWS
if ( source_hwnd )
2022-11-19 08:49:04 -05:00
PostMessage ( ( HWND ) ( uintptr_t ) source_hwnd , WM_SENDSTATUS , ( WPARAM ) ! ! p , ( LPARAM ) ( HWND ) main_window - > winId ( ) ) ;
2022-01-22 01:10:11 +02:00
# endif
2021-11-25 10:20:56 +01:00
}
// because we can't include nvr.h because it's got fields named new
2022-11-19 08:49:04 -05:00
extern int nvr_save ( void ) ;
2021-11-25 10:20:56 +01:00
void
plat_power_off ( void )
{
2022-02-17 11:51:24 +06:00
plat_mouse_capture ( 0 ) ;
2021-11-25 10:20:56 +01:00
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 ;
2022-07-11 03:44:30 +02:00
QTimer : : singleShot ( 0 , ( const QWidget * ) main_window , & QMainWindow : : close ) ;
2021-11-25 10:20:56 +01:00
}
2022-11-19 08:49:04 -05:00
void
set_language ( uint32_t id )
{
2021-11-25 10:20:56 +01:00
lang_id = id ;
}
2022-11-19 08:49:04 -05:00
extern " C++ " {
QMap < uint32_t , QPair < QString , QString > > ProgSettings : : lcid_langcode = {
{ 0x0405 , { " cs-CZ " , " Czech (Czech Republic) " } } ,
{ 0x0407 , { " de-DE " , " German (Germany) " } } ,
{ 0x0409 , { " en-US " , " English (United States) " } } ,
{ 0x0809 , { " en-GB " , " English (United Kingdom) " } } ,
{ 0x0C0A , { " es-ES " , " Spanish (Spain) " } } ,
{ 0x040B , { " fi-FI " , " Finnish (Finland) " } } ,
{ 0x040C , { " fr-FR " , " French (France) " } } ,
{ 0x041A , { " hr-HR " , " Croatian (Croatia) " } } ,
{ 0x040E , { " hu-HU " , " Hungarian (Hungary) " } } ,
{ 0x0410 , { " it-IT " , " Italian (Italy) " } } ,
{ 0x0411 , { " ja-JP " , " Japanese (Japan) " } } ,
{ 0x0412 , { " ko-KR " , " Korean (Korea) " } } ,
{ 0x0415 , { " pl-PL " , " Polish (Poland) " } } ,
{ 0x0416 , { " pt-BR " , " Portuguese (Brazil) " } } ,
{ 0x0816 , { " pt-PT " , " Portuguese (Portugal) " } } ,
{ 0x0419 , { " ru-RU " , " Russian (Russia) " } } ,
{ 0x0424 , { " sl-SI " , " Slovenian (Slovenia) " } } ,
{ 0x041F , { " tr-TR " , " Turkish (Turkey) " } } ,
{ 0x0422 , { " uk-UA " , " Ukrainian (Ukraine) " } } ,
{ 0x0804 , { " zh-CN " , " Chinese (China) " } } ,
{ 0x0404 , { " zh-TW " , " Chinese (Taiwan) " } } ,
{ 0xFFFF , { " system " , " (System Default) " } } ,
} ;
2022-01-08 13:40:45 +02:00
}
2022-01-08 16:39:51 +06:00
2021-11-25 10:20:56 +01:00
/* Sets up the program language before initialization. */
2022-11-19 08:49:04 -05:00
uint32_t
plat_language_code ( char * langcode )
{
for ( auto & curKey : ProgSettings : : lcid_langcode . keys ( ) ) {
if ( ProgSettings : : lcid_langcode [ curKey ] . first = = langcode ) {
2022-01-08 16:39:51 +06:00
return curKey ;
}
}
return 0xFFFF ;
2021-11-25 10:20:56 +01:00
}
/* Converts back the language code to LCID */
2022-11-19 08:49:04 -05:00
void
plat_language_code_r ( uint32_t lcid , char * outbuf , int len )
{
if ( ! ProgSettings : : lcid_langcode . contains ( lcid ) ) {
2022-01-08 16:39:51 +06:00
qstrncpy ( outbuf , " system " , len ) ;
return ;
}
qstrncpy ( outbuf , ProgSettings : : lcid_langcode [ lcid ] . first . toUtf8 ( ) . constData ( ) , len ) ;
2021-11-25 10:20:56 +01:00
return ;
}
2022-07-24 03:54:47 +02:00
# ifndef Q_OS_WINDOWS
2022-11-19 08:49:04 -05:00
void *
dynld_module ( const char * name , dllimp_t * table )
2021-11-25 10:20:56 +01:00
{
2022-11-19 08:49:04 -05:00
QString libraryName = name ;
QFileInfo fi ( libraryName ) ;
QStringList removeSuffixes = { " dll " , " dylib " , " so " } ;
2021-11-30 20:34:07 +01:00
if ( removeSuffixes . contains ( fi . suffix ( ) ) ) {
libraryName = fi . completeBaseName ( ) ;
}
auto lib = std : : unique_ptr < QLibrary > ( new QLibrary ( libraryName ) ) ;
2021-11-25 10:20:56 +01:00
if ( lib - > load ( ) ) {
2022-11-19 08:49:04 -05:00
for ( auto imp = table ; imp - > name ! = nullptr ; imp + + ) {
2021-11-30 20:34:07 +01:00
auto ptr = lib - > resolve ( imp - > name ) ;
if ( ptr = = nullptr ) {
2021-11-25 10:20:56 +01:00
return nullptr ;
}
2022-11-19 08:49:04 -05:00
auto imp_ptr = reinterpret_cast < void * * > ( imp - > func ) ;
* imp_ptr = reinterpret_cast < void * > ( ptr ) ;
2021-11-25 10:20:56 +01:00
}
2021-11-30 20:20:53 +01:00
} else {
return nullptr ;
2021-11-25 10:20:56 +01:00
}
return lib . release ( ) ;
}
2022-11-19 08:49:04 -05:00
void
dynld_close ( void * handle )
2021-11-25 10:20:56 +01:00
{
2022-11-19 08:49:04 -05:00
delete reinterpret_cast < QLibrary * > ( handle ) ;
2021-11-25 10:20:56 +01:00
}
2022-07-24 03:37:37 +02:00
# endif
2021-11-25 10:20:56 +01:00
2022-11-19 08:49:04 -05:00
void
startblit ( )
2021-11-25 10:20:56 +01:00
{
2021-12-08 11:05:52 +01:00
blitmx_contention + + ;
2022-08-01 13:26:07 +06:00
if ( blitmx . try_lock ( ) ) {
2021-12-08 11:05:52 +01:00
return ;
}
2022-08-01 13:26:07 +06:00
blitmx . lock ( ) ;
2021-11-25 10:20:56 +01:00
}
2022-11-19 08:49:04 -05:00
void
endblit ( )
2021-11-25 10:20:56 +01:00
{
2021-12-08 11:05:52 +01:00
blitmx_contention - - ;
2022-08-01 13:26:07 +06:00
blitmx . unlock ( ) ;
2021-12-08 11:05:52 +01:00
if ( blitmx_contention > 0 ) {
// a deadlock has been observed on linux when toggling via video_toggle_option
// because the mutex is typically unfair on linux
// => sleep if there's contention
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 1 ) ) ;
}
2021-11-25 10:20:56 +01:00
}
}
2021-12-02 19:35:08 +02:00
# ifdef Q_OS_WINDOWS
2022-11-19 08:49:04 -05:00
size_t
mbstoc16s ( uint16_t dst [ ] , const char src [ ] , int len )
2021-12-02 19:35:08 +02:00
{
2022-11-19 08:49:04 -05:00
if ( src = = NULL )
return 0 ;
if ( len < 0 )
return 0 ;
2021-12-02 19:35:08 +02:00
size_t ret = MultiByteToWideChar ( CP_UTF8 , 0 , src , - 1 , reinterpret_cast < LPWSTR > ( dst ) , dst = = NULL ? 0 : len ) ;
if ( ! ret ) {
2022-11-19 08:49:04 -05:00
return - 1 ;
2021-12-02 19:35:08 +02:00
}
return ret ;
}
2022-11-19 08:49:04 -05:00
size_t
c16stombs ( char dst [ ] , const uint16_t src [ ] , int len )
2021-12-02 19:35:08 +02:00
{
2022-11-19 08:49:04 -05:00
if ( src = = NULL )
return 0 ;
if ( len < 0 )
return 0 ;
2021-12-02 19:35:08 +02:00
size_t ret = WideCharToMultiByte ( CP_UTF8 , 0 , reinterpret_cast < LPCWCH > ( src ) , - 1 , dst , dst = = NULL ? 0 : len , NULL , NULL ) ;
if ( ! ret ) {
2022-11-19 08:49:04 -05:00
return - 1 ;
2021-12-02 19:35:08 +02:00
}
return ret ;
}
# endif
2021-12-31 12:36:55 +06:00
# ifdef _WIN32
2022-11-19 08:49:04 -05:00
# define LIB_NAME_FLUIDSYNTH "libfluidsynth.dll"
# define LIB_NAME_GS "gsdll32.dll"
# define LIB_NAME_FREETYPE "freetype.dll"
# define MOUSE_CAPTURE_KEYSEQ "F8+F12"
2021-12-31 12:36:55 +06:00
# else
2022-11-19 08:49:04 -05:00
# define LIB_NAME_FLUIDSYNTH "libfluidsynth"
# define LIB_NAME_GS "libgs"
# define LIB_NAME_FREETYPE "libfreetype"
# define MOUSE_CAPTURE_KEYSEQ "CTRL-END"
2021-12-31 12:36:55 +06:00
# endif
2022-01-08 16:39:51 +06:00
QMap < int , std : : wstring > ProgSettings : : translatedstrings ;
2021-12-31 12:36:55 +06:00
2022-11-19 08:49:04 -05:00
void
ProgSettings : : reloadStrings ( )
2021-12-31 12:36:55 +06:00
{
translatedstrings . clear ( ) ;
2022-01-04 01:24:10 +06:00
translatedstrings [ IDS_2077 ] = QCoreApplication : : translate ( " " , " Click to capture mouse " ) . toStdWString ( ) ;
2022-01-06 16:58:11 +06:00
translatedstrings [ IDS_2078 ] = QCoreApplication : : translate ( " " , " Press F8+F12 to release mouse " ) . replace ( " F8+F12 " , MOUSE_CAPTURE_KEYSEQ ) . replace ( " CTRL-END " , QLocale : : system ( ) . name ( ) = = " de_DE " ? " Strg+Ende " : " CTRL-END " ) . toStdWString ( ) ;
translatedstrings [ IDS_2079 ] = QCoreApplication : : translate ( " " , " Press F8+F12 or middle button to release mouse " ) . replace ( " F8+F12 " , MOUSE_CAPTURE_KEYSEQ ) . replace ( " CTRL-END " , QLocale : : system ( ) . name ( ) = = " de_DE " ? " Strg+Ende " : " CTRL-END " ) . toStdWString ( ) ;
2022-01-04 01:24:10 +06:00
translatedstrings [ IDS_2080 ] = QCoreApplication : : translate ( " " , " Failed to initialize FluidSynth " ) . toStdWString ( ) ;
2022-11-09 18:13:33 -05:00
translatedstrings [ IDS_2131 ] = QCoreApplication : : translate ( " " , " Invalid configuration " ) . toStdWString ( ) ;
2022-01-04 01:24:10 +06:00
translatedstrings [ IDS_4099 ] = QCoreApplication : : translate ( " " , " MFM/RLL or ESDI CD-ROM drives never existed " ) . toStdWString ( ) ;
2022-11-09 18:13:33 -05:00
translatedstrings [ IDS_2094 ] = QCoreApplication : : translate ( " " , " Failed to set up PCap " ) . toStdWString ( ) ;
translatedstrings [ IDS_2095 ] = QCoreApplication : : translate ( " " , " No PCap devices found " ) . toStdWString ( ) ;
translatedstrings [ IDS_2096 ] = QCoreApplication : : translate ( " " , " Invalid PCap device " ) . toStdWString ( ) ;
translatedstrings [ IDS_2111 ] = QCoreApplication : : translate ( " " , " Unable to initialize FreeType " ) . toStdWString ( ) ;
translatedstrings [ IDS_2112 ] = QCoreApplication : : translate ( " " , " Unable to initialize SDL, libsdl2 is required " ) . toStdWString ( ) ;
translatedstrings [ IDS_2130 ] = QCoreApplication : : translate ( " " , " Make sure libpcap is installed and that you are on a libpcap-compatible network connection. " ) . toStdWString ( ) ;
translatedstrings [ IDS_2115 ] = QCoreApplication : : translate ( " " , " Unable to initialize Ghostscript " ) . toStdWString ( ) ;
2022-01-04 01:24:10 +06:00
translatedstrings [ IDS_2063 ] = QCoreApplication : : translate ( " " , " Machine \" %hs \" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine. " ) . toStdWString ( ) ;
translatedstrings [ IDS_2064 ] = QCoreApplication : : translate ( " " , " Video card \" %hs \" is not available due to missing ROMs in the roms/video directory. Switching to an available video card. " ) . toStdWString ( ) ;
2022-11-13 22:16:18 -05:00
translatedstrings [ IDS_2163 ] = QCoreApplication : : translate ( " " , " Video card #2 \" %hs \" is not available due to missing ROMs in the roms/video directory. Disabling the second video card. " ) . toStdWString ( ) ;
2022-11-09 18:13:33 -05:00
translatedstrings [ IDS_2129 ] = QCoreApplication : : translate ( " " , " Hardware not available " ) . toStdWString ( ) ;
translatedstrings [ IDS_2143 ] = QCoreApplication : : translate ( " " , " Monitor in sleep mode " ) . toStdWString ( ) ;
translatedstrings [ IDS_2121 ] = QCoreApplication : : translate ( " " , " No ROMs found " ) . toStdWString ( ) ;
2022-04-08 10:45:46 +02:00
translatedstrings [ IDS_2056 ] = QCoreApplication : : translate ( " " , " 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. " ) . toStdWString ( ) ;
2023-05-23 11:53:59 -04:00
translatedstrings [ IDS_2167 ] = QCoreApplication : : translate ( " " , " Failed to initialize network driver " ) . toStdWString ( ) ;
translatedstrings [ IDS_2168 ] = QCoreApplication : : translate ( " " , " The network configuration will be switched to the null driver " ) . toStdWString ( ) ;
2022-01-04 01:24:10 +06:00
auto flsynthstr = QCoreApplication : : translate ( " " , " is required for FluidSynth MIDI output. " ) ;
2022-11-19 08:49:04 -05:00
if ( flsynthstr . contains ( " libfluidsynth " ) ) {
2022-01-04 01:24:10 +06:00
flsynthstr . replace ( " libfluidsynth " , LIB_NAME_FLUIDSYNTH ) ;
2022-11-19 08:49:04 -05:00
} else
flsynthstr . prepend ( LIB_NAME_FLUIDSYNTH ) ;
2022-11-09 18:13:33 -05:00
translatedstrings [ IDS_2134 ] = flsynthstr . toStdWString ( ) ;
2022-11-19 08:49:04 -05:00
auto gssynthstr = QCoreApplication : : translate ( " " , " is required for automatic conversion of PostScript files to PDF. \n \n Any documents sent to the generic PostScript printer will be saved as PostScript (.ps) files. " ) ;
if ( gssynthstr . contains ( " libgs " ) ) {
2022-01-04 01:24:10 +06:00
gssynthstr . replace ( " libgs " , LIB_NAME_GS ) ;
2022-11-19 08:49:04 -05:00
} else
gssynthstr . prepend ( LIB_NAME_GS ) ;
2022-11-09 18:13:33 -05:00
translatedstrings [ IDS_2133 ] = gssynthstr . toStdWString ( ) ;
2022-11-19 08:49:04 -05:00
auto ftsynthstr = QCoreApplication : : translate ( " " , " is required for ESC/P printer emulation. " ) ;
if ( ftsynthstr . contains ( " libfreetype " ) ) {
2022-01-04 01:24:10 +06:00
ftsynthstr . replace ( " libfreetype " , LIB_NAME_FREETYPE ) ;
2022-11-19 08:49:04 -05:00
} else
ftsynthstr . prepend ( LIB_NAME_FREETYPE ) ;
2022-11-09 18:13:33 -05:00
translatedstrings [ IDS_2132 ] = ftsynthstr . toStdWString ( ) ;
2021-12-31 12:36:55 +06:00
}
2022-11-19 08:49:04 -05:00
wchar_t *
plat_get_string ( int i )
2021-12-31 12:36:55 +06:00
{
2022-11-19 08:49:04 -05:00
if ( ProgSettings : : translatedstrings . empty ( ) )
ProgSettings : : reloadStrings ( ) ;
2022-01-08 16:39:51 +06:00
return ProgSettings : : translatedstrings [ i ] . data ( ) ;
2021-12-31 12:36:55 +06:00
}
2021-12-02 19:35:08 +02:00
int
plat_chdir ( char * path )
{
return QDir : : setCurrent ( QString ( path ) ) ? 0 : - 1 ;
}
2022-04-06 16:16:25 +06:00
2022-11-06 22:32:58 +06:00
void
plat_get_global_config_dir ( char * strptr )
{
# ifdef __APPLE__
auto dir = QDir ( QStandardPaths : : standardLocations ( QStandardPaths : : GenericConfigLocation ) [ 0 ] + " /net.86Box.86Box/ " ) ;
# else
auto dir = QDir ( QStandardPaths : : standardLocations ( QStandardPaths : : GenericConfigLocation ) [ 0 ] + " /86Box/ " ) ;
# endif
if ( ! dir . exists ( ) ) dir . mkpath ( " . " ) ;
strncpy ( strptr , dir . canonicalPath ( ) . toUtf8 ( ) . constData ( ) , 1024 ) ;
}
2022-04-06 16:16:25 +06:00
void
plat_init_rom_paths ( )
{
2022-04-08 00:58:38 +02:00
auto paths = QStandardPaths : : standardLocations ( QStandardPaths : : GenericDataLocation ) ;
2022-04-06 16:16:25 +06:00
2022-04-08 00:58:38 +02:00
# ifdef _WIN32
// HACK: The standard locations returned for GenericDataLocation include
// the EXE path and a `data` directory within it as the last two entries.
2022-04-06 16:16:25 +06:00
2022-04-08 00:58:38 +02:00
// Remove the entries as we don't need them.
paths . removeLast ( ) ;
paths . removeLast ( ) ;
2022-04-06 16:16:25 +06:00
# endif
2022-04-08 00:58:38 +02:00
2022-11-19 08:49:04 -05:00
for ( auto & path : paths ) {
2022-04-08 10:20:01 +02:00
# ifdef __APPLE__
rom_add_path ( QDir ( path ) . filePath ( " net.86Box.86Box/roms " ) . toUtf8 ( ) . constData ( ) ) ;
# else
2022-04-08 00:46:30 +02:00
rom_add_path ( QDir ( path ) . filePath ( " 86Box/roms " ) . toUtf8 ( ) . constData ( ) ) ;
2022-04-08 10:20:01 +02:00
# endif
2022-04-08 00:58:38 +02:00
}
2022-04-06 16:16:25 +06:00
}