2021-08-22 16:32:52 +06:00
# ifdef __linux__
2022-09-18 17:17:34 -04:00
# define _FILE_OFFSET_BITS 64
# define _LARGEFILE64_SOURCE 1
2021-08-22 16:32:52 +06:00
# endif
2021-09-09 23:51:26 +06:00
# include <SDL.h>
2021-08-22 16:32:52 +06:00
# include <stdlib.h>
2021-08-25 22:34:58 +06:00
# include <stdbool.h>
2021-08-22 16:32:52 +06:00
# include <stdio.h>
2021-08-25 22:34:58 +06:00
# include <string.h>
2021-08-22 16:32:52 +06:00
# include <time.h>
# include <sys/time.h>
# include <sys/param.h>
# include <sys/types.h>
# include <sys/stat.h>
2021-10-20 00:37:23 +06:00
# include <sys/mman.h>
2021-08-22 16:32:52 +06:00
# include <unistd.h>
# include <errno.h>
# include <inttypes.h>
# include <dlfcn.h>
2021-08-29 00:53:18 +06:00
# include <wchar.h>
2022-04-08 15:00:35 +06:00
# include <pwd.h>
2021-12-17 22:15:21 +02:00
# include <stdatomic.h>
2021-09-09 23:51:26 +06:00
2021-08-22 16:32:52 +06:00
# include <86box/86box.h>
2022-04-06 16:16:25 +06:00
# include <86box/mem.h>
# include <86box/rom.h>
2021-08-23 00:47:07 +06:00
# include <86box/keyboard.h>
2021-08-23 15:56:24 +06:00
# include <86box/mouse.h>
2021-08-22 16:32:52 +06:00
# include <86box/config.h>
2022-04-19 23:06:39 +02:00
# include <86box/path.h>
2021-08-22 16:32:52 +06:00
# include <86box/plat.h>
# include <86box/plat_dynld.h>
2022-04-19 23:06:39 +02:00
# include <86box/thread.h>
2021-08-22 16:32:52 +06:00
# include <86box/device.h>
# include <86box/gameport.h>
# include <86box/unix_sdl.h>
# include <86box/timer.h>
# include <86box/nvr.h>
2023-07-04 21:34:25 +05:00
# include <86box/version.h>
2022-07-29 16:56:48 +06:00
# include <86box/video.h>
2021-08-28 00:37:09 +06:00
# include <86box/ui.h>
2022-03-12 20:20:25 -03:00
# include <86box/gdbstub.h>
2021-08-23 14:09:43 +06:00
2022-04-08 00:58:38 +02:00
# ifdef __APPLE__
2022-09-18 17:17:34 -04:00
# include "macOSXGlue.h"
2022-04-08 00:58:38 +02:00
# endif
2022-09-18 17:17:34 -04:00
static int first_use = 1 ;
static uint64_t StartingTime ;
2021-08-22 16:32:52 +06:00
static uint64_t Frequency ;
2022-09-18 17:17:34 -04:00
int rctrl_is_lalt ;
int update_icons ;
int kbd_req_capture ;
int hide_status_bar ;
int hide_tool_bar ;
int fixed_size_x = 640 ;
int fixed_size_y = 480 ;
extern int title_set ;
extern wchar_t sdl_win_title [ 512 ] ;
plat_joystick_t plat_joystick_state [ MAX_PLAT_JOYSTICKS ] ;
joystick_t joystick_state [ MAX_JOYSTICKS ] ;
int joysticks_present ;
SDL_mutex * blitmtx ;
SDL_threadID eventthread ;
static int exit_event = 0 ;
static int fullscreen_pending = 0 ;
2023-05-29 01:30:51 -04:00
uint32_t lang_id = 0x0409 ; // Multilangual UI variables, for now all set to LCID of en-US
uint32_t lang_sys = 0x0409 ; // Multilangual UI variables, for now all set to LCID of en-US
2022-09-18 17:17:34 -04:00
char icon_set [ 256 ] = " " ; /* name of the iconset to be used */
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 ,
2021-08-23 00:47:07 +06:00
[ SDL_SCANCODE_RIGHTBRACKET ] = 0x1B ,
2022-09-18 17:17:34 -04:00
[ 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 ,
2021-08-23 00:47:07 +06:00
[ SDL_SCANCODE_NUMLOCKCLEAR ] = 0x45 ,
2022-09-18 17:17:34 -04:00
[ 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 ,
2021-08-23 00:47:07 +06:00
[ SDL_SCANCODE_KP_DIVIDE ] = 0x135 ,
2022-09-18 17:17:34 -04:00
[ 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 ,
2021-09-06 22:06:02 +06:00
[ SDL_SCANCODE_KP_PERIOD ] = 0x53 ,
2022-09-18 17:17:34 -04:00
[ SDL_SCANCODE_LGUI ] = 0x15B ,
[ SDL_SCANCODE_RGUI ] = 0x15C ,
2021-09-08 13:49:04 +06:00
[ SDL_SCANCODE_APPLICATION ] = 0x15D ,
[ SDL_SCANCODE_PRINTSCREEN ] = 0x137
2021-08-23 00:47:07 +06:00
} ;
2022-09-18 17:17:34 -04:00
typedef struct sdl_blit_params {
2023-05-29 01:30:51 -04:00
int x ;
int y ;
int w ;
int h ;
2021-08-22 16:32:52 +06:00
} sdl_blit_params ;
2022-09-18 17:17:34 -04:00
sdl_blit_params params = { 0 , 0 , 0 , 0 } ;
int blitreq = 0 ;
2021-08-22 16:32:52 +06:00
2022-09-18 17:17:34 -04:00
void *
dynld_module ( const char * name , dllimp_t * table )
2021-08-22 16:32:52 +06:00
{
2022-09-18 17:17:34 -04:00
dllimp_t * imp ;
void * modhandle = dlopen ( name , RTLD_LAZY | RTLD_GLOBAL ) ;
if ( modhandle ) {
for ( imp = table ; imp - > name ! = NULL ; imp + + ) {
if ( ( * ( void * * ) imp - > func = dlsym ( modhandle , imp - > name ) ) = = NULL ) {
2021-08-22 16:32:52 +06:00
dlclose ( modhandle ) ;
return NULL ;
}
}
}
return modhandle ;
}
void
plat_tempfile ( char * bufp , char * prefix , char * suffix )
{
2022-09-18 17:17:34 -04:00
struct tm * calendertime ;
2021-08-22 16:32:52 +06:00
struct timeval t ;
2022-09-18 17:17:34 -04:00
time_t curtime ;
2021-08-22 16:32:52 +06:00
if ( prefix ! = NULL )
2022-09-18 17:17:34 -04:00
sprintf ( bufp , " %s- " , prefix ) ;
else
strcpy ( bufp , " " ) ;
2021-08-22 16:32:52 +06:00
gettimeofday ( & t , NULL ) ;
2022-09-18 17:17:34 -04:00
curtime = time ( NULL ) ;
2021-08-22 16:32:52 +06:00
calendertime = localtime ( & curtime ) ;
2021-08-25 02:01:39 +06:00
sprintf ( & bufp [ strlen ( bufp ) ] , " %d%02d%02d-%02d%02d%02d-%03ld%s " , calendertime - > tm_year , calendertime - > tm_mon , calendertime - > tm_mday , calendertime - > tm_hour , calendertime - > tm_min , calendertime - > tm_sec , t . tv_usec / 1000 , suffix ) ;
2021-08-22 16:32:52 +06:00
}
int
plat_getcwd ( char * bufp , int max )
{
return getcwd ( bufp , max ) ! = 0 ;
}
int
2022-09-18 17:17:34 -04:00
plat_chdir ( char * str )
2021-08-22 16:32:52 +06:00
{
return chdir ( str ) ;
}
2022-09-18 17:17:34 -04:00
void
dynld_close ( void * handle )
2021-08-22 16:32:52 +06:00
{
2022-09-18 17:17:34 -04:00
dlclose ( handle ) ;
2021-08-22 16:32:52 +06:00
}
2022-09-18 17:17:34 -04:00
wchar_t *
plat_get_string ( int i )
2021-08-22 16:32:52 +06:00
{
2022-09-18 17:17:34 -04:00
switch ( i ) {
2021-08-23 14:09:43 +06:00
case IDS_2077 :
2022-03-15 04:19:10 +05:00
return L " Click to capture mouse " ;
2021-08-23 14:09:43 +06:00
case IDS_2078 :
2021-08-23 15:56:24 +06:00
return L " Press CTRL-END to release mouse " ;
2021-08-23 14:09:43 +06:00
case IDS_2079 :
2021-08-23 15:56:24 +06:00
return L " Press CTRL-END or middle button to release mouse " ;
2022-11-08 04:18:33 -05:00
case IDS_2131 :
2022-03-15 04:19:10 +05:00
return L " Invalid configuration " ;
2021-08-28 00:37:09 +06:00
case IDS_4099 :
return L " MFM/RLL or ESDI CD-ROM drives never existed " ;
case IDS_2094 :
2022-11-08 04:18:33 -05:00
return L " Failed to set up PCap " ;
2022-03-15 04:19:10 +05:00
case IDS_2095 :
2022-11-08 04:18:33 -05:00
return L " No PCap devices found " ;
case IDS_2096 :
2022-03-15 04:19:10 +05:00
return L " Invalid PCap device " ;
2022-11-08 04:18:33 -05:00
case IDS_2112 :
2021-08-28 00:37:09 +06:00
return L " Unable to initialize SDL, libsdl2 is required " ;
2022-03-15 04:19:10 +05:00
case IDS_2133 :
2022-11-08 04:18:33 -05:00
return L " libgs 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. " ;
case IDS_2130 :
2021-08-28 00:37:09 +06:00
return L " Make sure libpcap is installed and that you are on a libpcap-compatible network connection. " ;
2022-11-08 04:18:33 -05:00
case IDS_2115 :
2021-08-28 00:37:09 +06:00
return L " Unable to initialize Ghostscript " ;
2021-10-16 00:14:26 +06:00
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. " ;
2022-11-08 04:18:33 -05:00
case IDS_2129 :
2021-10-16 00:14:26 +06:00
return L " Hardware not available " ;
2022-11-08 04:18:33 -05:00
case IDS_2143 :
2022-03-15 04:19:10 +05:00
return L " Monitor in sleep mode " ;
2021-08-23 14:09:43 +06:00
}
2021-08-22 16:32:52 +06:00
return L " " ;
}
FILE *
plat_fopen ( const char * path , const char * mode )
{
return fopen ( path , mode ) ;
}
FILE *
plat_fopen64 ( const char * path , const char * mode )
{
return fopen ( path , mode ) ;
}
int
2022-04-19 23:06:39 +02:00
path_abs ( char * path )
2021-08-22 16:32:52 +06:00
{
return path [ 0 ] = = ' / ' ;
}
2022-03-04 01:17:38 +06:00
void
2022-09-18 17:17:34 -04:00
path_normalize ( char * path )
2022-03-04 01:17:38 +06:00
{
2022-03-04 14:00:24 +06:00
/* No-op. */
2022-03-04 01:17:38 +06:00
}
2021-08-22 16:32:52 +06:00
void
2022-04-19 23:06:39 +02:00
path_slash ( char * path )
2021-08-22 16:32:52 +06:00
{
2023-05-29 01:30:51 -04:00
if ( path [ strlen ( path ) - 1 ] ! = ' / ' ) {
2022-09-18 17:17:34 -04:00
strcat ( path , " / " ) ;
2021-08-22 16:32:52 +06:00
}
2022-04-19 23:06:39 +02:00
path_normalize ( path ) ;
2021-08-22 16:32:52 +06:00
}
2023-08-22 15:11:37 -04:00
const char *
2023-08-18 18:28:38 +02:00
path_get_slash ( char * path )
{
char * ret = " " ;
if ( path [ strlen ( path ) - 1 ] ! = ' / ' )
ret = " / " ;
return ret ;
}
2021-08-22 16:32:52 +06:00
void
plat_put_backslash ( char * s )
{
int c = strlen ( s ) - 1 ;
if ( s [ c ] ! = ' / ' )
2022-09-18 17:17:34 -04:00
s [ c ] = ' / ' ;
2021-08-22 16:32:52 +06:00
}
/* Return the last element of a pathname. */
char *
plat_get_basename ( const char * path )
{
2022-09-18 17:17:34 -04:00
int c = ( int ) strlen ( path ) ;
2021-08-22 16:32:52 +06:00
while ( c > 0 ) {
2022-09-18 17:17:34 -04:00
if ( path [ c ] = = ' / ' )
return ( ( char * ) & path [ c + 1 ] ) ;
c - - ;
2021-08-22 16:32:52 +06:00
}
2022-09-18 17:17:34 -04:00
return ( ( char * ) path ) ;
2021-08-22 16:32:52 +06:00
}
char *
2022-04-19 23:06:39 +02:00
path_get_filename ( char * s )
2021-08-22 16:32:52 +06:00
{
int c = strlen ( s ) - 1 ;
while ( c > 0 ) {
2022-09-18 17:17:34 -04:00
if ( s [ c ] = = ' / ' | | s [ c ] = = ' \\ ' )
return ( & s [ c + 1 ] ) ;
c - - ;
2021-08-22 16:32:52 +06:00
}
2023-05-29 01:30:51 -04:00
return s ;
2021-08-22 16:32:52 +06:00
}
char *
2022-04-19 23:06:39 +02:00
path_get_extension ( char * s )
2021-08-22 16:32:52 +06:00
{
int c = strlen ( s ) - 1 ;
if ( c < = 0 )
2023-05-29 01:30:51 -04:00
return s ;
2021-08-22 16:32:52 +06:00
while ( c & & s [ c ] ! = ' . ' )
2022-09-18 17:17:34 -04:00
c - - ;
2021-08-22 16:32:52 +06:00
if ( ! c )
2022-09-18 17:17:34 -04:00
return ( & s [ strlen ( s ) ] ) ;
2021-08-22 16:32:52 +06:00
2022-09-18 17:17:34 -04:00
return ( & s [ c + 1 ] ) ;
2021-08-22 16:32:52 +06:00
}
void
2022-04-19 23:06:39 +02:00
path_append_filename ( char * dest , const char * s1 , const char * s2 )
2021-08-22 16:32:52 +06:00
{
strcpy ( dest , s1 ) ;
2022-04-19 23:06:39 +02:00
path_slash ( dest ) ;
2021-08-22 16:32:52 +06:00
strcat ( dest , s2 ) ;
}
int
plat_dir_check ( char * path )
{
struct stat dummy ;
2022-09-18 17:17:34 -04:00
if ( stat ( path , & dummy ) < 0 ) {
2021-08-22 16:32:52 +06:00
return 0 ;
}
return S_ISDIR ( dummy . st_mode ) ;
}
int
plat_dir_create ( char * path )
{
return mkdir ( path , S_IRWXU ) ;
}
2021-10-16 20:12:49 -03:00
void *
plat_mmap ( size_t size , uint8_t executable )
{
2021-10-19 23:44:47 +06:00
# if defined __APPLE__ && defined MAP_JIT
2022-01-07 14:58:59 +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 ) ;
2021-10-19 23:44:47 +06:00
# else
2022-09-18 17:17:34 -04:00
void * ret = mmap ( 0 , size , PROT_READ | PROT_WRITE | ( executable ? PROT_EXEC : 0 ) , MAP_ANON | MAP_PRIVATE , - 1 , 0 ) ;
2021-10-19 23:44:47 +06:00
# endif
2021-10-16 20:12:49 -03:00
return ( ret < 0 ) ? NULL : ret ;
}
void
plat_munmap ( void * ptr , size_t size )
{
munmap ( ptr , size ) ;
}
2021-08-22 16:32:52 +06:00
uint64_t
plat_timer_read ( void )
{
return SDL_GetPerformanceCounter ( ) ;
}
static uint64_t
plat_get_ticks_common ( void )
{
2023-05-29 01:30:51 -04:00
uint64_t EndingTime ;
uint64_t ElapsedMicroseconds ;
2021-08-22 16:32:52 +06:00
if ( first_use ) {
2022-09-18 17:17:34 -04:00
Frequency = SDL_GetPerformanceFrequency ( ) ;
StartingTime = SDL_GetPerformanceCounter ( ) ;
first_use = 0 ;
2021-08-22 16:32:52 +06:00
}
2022-09-18 17:17:34 -04:00
EndingTime = SDL_GetPerformanceCounter ( ) ;
2021-08-22 16:32:52 +06:00
ElapsedMicroseconds = ( ( EndingTime - StartingTime ) * 1000000 ) / Frequency ;
return ElapsedMicroseconds ;
}
uint32_t
plat_get_ticks ( void )
{
2022-09-18 17:17:34 -04:00
return ( uint32_t ) ( plat_get_ticks_common ( ) / 1000 ) ;
2021-08-22 16:32:52 +06:00
}
uint32_t
plat_get_micro_ticks ( void )
{
2022-09-18 17:17:34 -04:00
return ( uint32_t ) plat_get_ticks_common ( ) ;
2021-08-22 16:32:52 +06:00
}
2022-09-18 17:17:34 -04:00
void
plat_remove ( char * path )
2021-08-22 16:32:52 +06:00
{
remove ( path ) ;
}
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 )
{
SDL_Delay ( count ) ;
}
void
ui_sb_update_tip ( int arg )
{
}
void
2022-12-19 19:45:39 -05:00
ui_sb_update_panes ( void )
2021-08-22 16:32:52 +06:00
{
}
2021-12-05 11:48:31 +01:00
void
2022-12-19 19:45:39 -05:00
ui_sb_update_text ( void )
2021-12-05 11:48:31 +01:00
{
}
2021-08-22 16:32:52 +06:00
void
2022-04-19 23:06:39 +02:00
path_get_dirname ( char * dest , const char * path )
2021-08-22 16:32:52 +06:00
{
2022-09-18 17:17:34 -04:00
int c = ( int ) strlen ( path ) ;
2021-08-22 16:32:52 +06:00
char * ptr ;
2022-09-18 17:17:34 -04:00
ptr = ( char * ) path ;
2021-08-22 16:32:52 +06:00
while ( c > 0 ) {
2022-09-18 17:17:34 -04:00
if ( path [ c ] = = ' / ' | | path [ c ] = = ' \\ ' ) {
ptr = ( char * ) & path [ c ] ;
break ;
}
c - - ;
2021-08-22 16:32:52 +06:00
}
/* Copy to destination. */
while ( path < ptr )
2022-09-18 17:17:34 -04:00
* dest + + = * path + + ;
2021-08-22 16:32:52 +06:00
* dest = ' \0 ' ;
}
volatile int cpu_thread_run = 1 ;
2022-09-18 17:17:34 -04:00
void
ui_sb_set_text_w ( wchar_t * wstr )
2021-08-22 16:32:52 +06:00
{
}
2022-09-18 17:17:34 -04:00
int
stricmp ( const char * s1 , const char * s2 )
2021-08-22 16:32:52 +06:00
{
return strcasecmp ( s1 , s2 ) ;
}
2022-09-18 17:17:34 -04:00
int
strnicmp ( const char * s1 , const char * s2 , size_t n )
2021-08-22 16:32:52 +06:00
{
return strncasecmp ( s1 , s2 , n ) ;
}
void
main_thread ( void * param )
{
2023-05-29 01:30:51 -04:00
uint32_t old_time ;
uint32_t new_time ;
int drawits ;
int frames ;
2021-08-22 16:32:52 +06:00
2021-08-28 23:06:07 +06:00
SDL_SetThreadPriority ( SDL_THREAD_PRIORITY_HIGH ) ;
2021-08-22 16:32:52 +06:00
framecountx = 0 ;
2022-09-18 17:17:34 -04:00
// title_update = 1;
2021-08-22 16:32:52 +06:00
old_time = SDL_GetTicks ( ) ;
drawits = frames = 0 ;
while ( ! is_quit & & cpu_thread_run ) {
2022-09-18 17:17:34 -04:00
/* See if it is time to run a frame of code. */
new_time = SDL_GetTicks ( ) ;
2022-03-16 00:33:01 -03:00
# ifdef USE_GDBSTUB
2022-09-18 17:17:34 -04:00
if ( gdbstub_next_asap & & ( drawits < = 0 ) )
drawits = 10 ;
else
2022-03-16 00:33:01 -03:00
# endif
2022-09-18 17:17:34 -04:00
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 ) {
nvr_save ( ) ;
nvr_dosave = 0 ;
frames = 0 ;
}
} else /* Just so we dont overload the host OS. */
SDL_Delay ( 1 ) ;
/* If needed, handle a screen resize. */
if ( atomic_load ( & doresize_monitors [ 0 ] ) & & ! video_fullscreen & & ! is_quit ) {
if ( vid_resize & 2 )
plat_resize ( fixed_size_x , fixed_size_y ) ;
else
plat_resize ( scrnsz_x , scrnsz_y ) ;
atomic_store ( & doresize_monitors [ 0 ] , 1 ) ;
}
2021-08-22 16:32:52 +06:00
}
is_quit = 1 ;
}
2022-09-18 17:17:34 -04:00
thread_t * thMain = NULL ;
2021-08-22 16:32:52 +06:00
void
do_start ( void )
{
/* We have not stopped yet. */
is_quit = 0 ;
/* Initialize the high-precision timer. */
SDL_InitSubSystem ( SDL_INIT_TIMER ) ;
timer_freq = SDL_GetPerformanceFrequency ( ) ;
/* Start the emulator, really. */
thMain = thread_create ( main_thread , NULL ) ;
}
void
do_stop ( void )
{
2022-09-18 17:17:34 -04:00
if ( SDL_ThreadID ( ) ! = eventthread ) {
2021-08-29 15:41:06 +06:00
exit_event = 1 ;
return ;
}
2022-09-18 17:17:34 -04:00
if ( blitreq ) {
2021-08-23 17:26:04 +06:00
blitreq = 0 ;
video_blit_complete ( ) ;
}
2022-09-18 17:17:34 -04:00
while ( SDL_TryLockMutex ( blitmtx ) = = SDL_MUTEX_TIMEDOUT ) {
if ( blitreq ) {
2021-08-29 15:41:06 +06:00
blitreq = 0 ;
video_blit_complete ( ) ;
}
}
startblit ( ) ;
2021-08-23 17:26:04 +06:00
2021-08-29 15:41:06 +06:00
is_quit = 1 ;
2021-08-22 16:32:52 +06:00
sdl_close ( ) ;
2021-08-23 17:26:04 +06:00
2021-08-22 16:32:52 +06:00
pc_close ( thMain ) ;
thMain = NULL ;
}
2022-09-18 17:17:34 -04:00
int
ui_msgbox ( int flags , void * message )
2021-08-22 16:32:52 +06:00
{
2021-10-13 23:41:02 +06:00
return ui_msgbox_header ( flags , NULL , message ) ;
}
2022-09-18 17:17:34 -04:00
int
ui_msgbox_header ( int flags , void * header , void * message )
2021-10-13 23:41:02 +06:00
{
2022-09-18 17:17:34 -04:00
SDL_MessageBoxData msgdata ;
2021-10-13 23:41:02 +06:00
SDL_MessageBoxButtonData msgbtn ;
2022-09-18 17:17:34 -04:00
if ( ! header )
2023-02-03 02:22:46 -05:00
header = ( void * ) ( flags & MBX_ANSI ) ? " 86Box " : L " 86Box " ;
2022-09-18 17:17:34 -04:00
if ( header < = ( void * ) 7168 )
2023-02-03 02:22:46 -05:00
header = ( void * ) plat_get_string ( ( int ) header ) ;
2022-09-18 17:17:34 -04:00
if ( message < = ( void * ) 7168 )
2023-02-03 02:22:46 -05:00
message = ( void * ) plat_get_string ( ( int ) message ) ;
2021-10-13 23:41:02 +06:00
msgbtn . buttonid = 1 ;
2022-09-18 17:17:34 -04:00
msgbtn . text = " OK " ;
msgbtn . flags = 0 ;
2021-10-13 23:41:02 +06:00
memset ( & msgdata , 0 , sizeof ( SDL_MessageBoxData ) ) ;
msgdata . numbuttons = 1 ;
2022-09-18 17:17:34 -04:00
msgdata . buttons = & msgbtn ;
int msgflags = 0 ;
if ( msgflags & MBX_FATAL )
msgflags | = SDL_MESSAGEBOX_ERROR ;
else if ( msgflags & MBX_ERROR | | msgflags & MBX_WARNING )
msgflags | = SDL_MESSAGEBOX_WARNING ;
else
msgflags | = SDL_MESSAGEBOX_INFORMATION ;
2021-10-13 23:41:02 +06:00
msgdata . flags = msgflags ;
2022-09-18 17:17:34 -04:00
if ( flags & MBX_ANSI ) {
int button = 0 ;
msgdata . title = header ;
2021-10-13 23:41:02 +06:00
msgdata . message = message ;
SDL_ShowMessageBox ( & msgdata , & button ) ;
return button ;
2022-09-18 17:17:34 -04:00
} else {
int button = 0 ;
char * res = SDL_iconv_string ( " UTF-8 " , sizeof ( wchar_t ) = = 2 ? " UTF-16LE " : " UTF-32LE " , ( char * ) message , wcslen ( message ) * sizeof ( wchar_t ) + sizeof ( wchar_t ) ) ;
char * res2 = SDL_iconv_string ( " UTF-8 " , sizeof ( wchar_t ) = = 2 ? " UTF-16LE " : " UTF-32LE " , ( char * ) header , wcslen ( header ) * sizeof ( wchar_t ) + sizeof ( wchar_t ) ) ;
2021-10-13 23:41:02 +06:00
msgdata . message = res ;
2022-09-18 17:17:34 -04:00
msgdata . title = res2 ;
2021-10-13 23:41:02 +06:00
SDL_ShowMessageBox ( & msgdata , & button ) ;
free ( res ) ;
free ( res2 ) ;
return button ;
}
2021-08-22 16:32:52 +06:00
return 0 ;
}
2022-09-18 17:17:34 -04:00
void
plat_get_exe_name ( char * s , int size )
2021-08-22 16:32:52 +06:00
{
2022-09-18 17:17:34 -04:00
char * basepath = SDL_GetBasePath ( ) ;
2021-08-23 14:09:43 +06:00
snprintf ( s , size , " %s%s " , basepath , basepath [ strlen ( basepath ) - 1 ] = = ' / ' ? " 86box " : " /86box " ) ;
2021-08-22 16:32:52 +06:00
}
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 ;
}
2022-09-18 17:17:34 -04:00
void
ui_sb_bugui ( char * str )
2021-08-22 16:32:52 +06:00
{
}
2021-08-23 15:56:24 +06:00
2022-09-18 17:17:34 -04:00
extern void sdl_blit ( int x , int y , int w , int h ) ;
2021-08-22 16:32:52 +06:00
2022-09-18 17:17:34 -04:00
typedef struct mouseinputdata {
2023-05-29 01:30:51 -04:00
int deltax ;
int deltay ;
int deltaz ;
2021-08-23 15:56:24 +06:00
int mousebuttons ;
} mouseinputdata ;
2022-09-18 17:17:34 -04:00
SDL_mutex * mousemutex ;
2023-05-29 01:30:51 -04:00
int real_sdl_w ;
int real_sdl_h ;
2022-09-18 17:17:34 -04:00
void
ui_sb_set_ready ( int ready )
{
}
char * xargv [ 512 ] ;
2021-08-25 22:34:58 +06:00
// From musl.
2022-09-18 17:17:34 -04:00
char *
local_strsep ( char * * str , const char * sep )
2021-08-25 22:34:58 +06:00
{
2023-05-29 01:30:51 -04:00
char * s = * str ;
char * end ;
2022-09-18 17:17:34 -04:00
if ( ! s )
return NULL ;
end = s + strcspn ( s , sep ) ;
if ( * end )
* end + + = 0 ;
else
end = 0 ;
* str = end ;
return s ;
2021-08-25 22:34:58 +06:00
}
2021-08-25 15:17:46 +06:00
2021-08-28 00:45:35 +06:00
void
plat_pause ( int p )
{
static wchar_t oldtitle [ 512 ] ;
2022-09-18 17:17:34 -04:00
wchar_t title [ 512 ] ;
2021-08-28 00:45:35 +06:00
2021-10-17 04:52:53 +05:00
if ( ( p = = 0 ) & & ( time_sync & TIME_SYNC_ENABLED ) )
2022-09-18 17:17:34 -04:00
nvr_time_sync ( ) ;
2021-10-17 04:52:53 +05:00
2021-08-28 00:45:35 +06:00
dopause = p ;
if ( p ) {
2022-09-18 17:17:34 -04:00
wcsncpy ( oldtitle , ui_window_title ( NULL ) , sizeof_w ( oldtitle ) - 1 ) ;
wcscpy ( title , oldtitle ) ;
wcscat ( title , L " - PAUSED " ) ;
ui_window_title ( title ) ;
2021-08-28 00:45:35 +06:00
} else {
2022-09-18 17:17:34 -04:00
ui_window_title ( oldtitle ) ;
2021-08-28 00:45:35 +06:00
}
}
2021-08-26 17:09:39 +06:00
2022-04-06 16:16:25 +06:00
void
2022-12-19 19:45:39 -05:00
plat_init_rom_paths ( void )
2022-04-06 16:16:25 +06:00
{
# ifndef __APPLE__
if ( getenv ( " XDG_DATA_HOME " ) ) {
char xdg_rom_path [ 1024 ] = { 0 } ;
strncpy ( xdg_rom_path , getenv ( " XDG_DATA_HOME " ) , 1024 ) ;
2022-04-19 23:06:39 +02:00
path_slash ( xdg_rom_path ) ;
2022-04-06 16:16:25 +06:00
strncat ( xdg_rom_path , " 86Box/ " , 1024 ) ;
if ( ! plat_dir_check ( xdg_rom_path ) )
plat_dir_create ( xdg_rom_path ) ;
strcat ( xdg_rom_path , " roms/ " ) ;
if ( ! plat_dir_check ( xdg_rom_path ) )
plat_dir_create ( xdg_rom_path ) ;
2022-04-08 00:46:30 +02:00
rom_add_path ( xdg_rom_path ) ;
2022-04-06 16:16:25 +06:00
} else {
char home_rom_path [ 1024 ] = { 0 } ;
snprintf ( home_rom_path , 1024 , " %s/.local/share/86Box/ " , getenv ( " HOME " ) ? getenv ( " HOME " ) : getpwuid ( getuid ( ) ) - > pw_dir ) ;
if ( ! plat_dir_check ( home_rom_path ) )
plat_dir_create ( home_rom_path ) ;
strcat ( home_rom_path , " roms/ " ) ;
if ( ! plat_dir_check ( home_rom_path ) )
plat_dir_create ( home_rom_path ) ;
2022-04-08 00:46:30 +02:00
rom_add_path ( home_rom_path ) ;
2022-04-06 16:16:25 +06:00
}
if ( getenv ( " XDG_DATA_DIRS " ) ) {
2022-09-18 17:17:34 -04:00
char * xdg_rom_paths = strdup ( getenv ( " XDG_DATA_DIRS " ) ) ;
char * xdg_rom_paths_orig = xdg_rom_paths ;
char * cur_xdg_rom_path = NULL ;
2022-04-06 16:16:25 +06:00
if ( xdg_rom_paths ) {
while ( xdg_rom_paths [ strlen ( xdg_rom_paths ) - 1 ] = = ' : ' ) {
xdg_rom_paths [ strlen ( xdg_rom_paths ) - 1 ] = ' \0 ' ;
}
while ( ( cur_xdg_rom_path = local_strsep ( & xdg_rom_paths , " ; " ) ) ! = NULL ) {
char real_xdg_rom_path [ 1024 ] = { ' \0 ' } ;
strcat ( real_xdg_rom_path , cur_xdg_rom_path ) ;
2022-04-19 23:06:39 +02:00
path_slash ( real_xdg_rom_path ) ;
2022-04-06 16:16:25 +06:00
strcat ( real_xdg_rom_path , " 86Box/roms/ " ) ;
2022-04-08 00:46:30 +02:00
rom_add_path ( real_xdg_rom_path ) ;
2022-04-06 16:16:25 +06:00
}
}
free ( xdg_rom_paths_orig ) ;
} else {
2022-04-08 00:46:30 +02:00
rom_add_path ( " /usr/local/share/86Box/roms/ " ) ;
rom_add_path ( " /usr/share/86Box/roms/ " ) ;
2022-04-06 16:16:25 +06:00
}
2022-04-07 00:57:16 +06:00
# else
2022-09-18 17:17:34 -04:00
char default_rom_path [ 1024 ] = { ' \ 0 ' } ;
2022-04-08 00:58:38 +02:00
getDefaultROMPath ( default_rom_path ) ;
2022-05-21 11:23:14 +02:00
rom_add_path ( default_rom_path ) ;
2022-04-06 16:16:25 +06:00
# endif
}
2022-11-06 22:32:58 +06:00
void
plat_get_global_config_dir ( char * strptr )
{
# ifdef __APPLE__
2023-04-09 00:51:59 +04:00
char * prefPath = SDL_GetPrefPath ( NULL , " net.86Box.86Box " ) ;
2022-11-06 22:32:58 +06:00
# else
2023-02-28 23:24:58 -05:00
char * prefPath = SDL_GetPrefPath ( NULL , " 86Box " ) ;
2022-11-06 22:32:58 +06:00
# endif
strncpy ( strptr , prefPath , 1024 ) ;
path_slash ( strptr ) ;
}
2022-09-18 17:17:34 -04:00
bool
process_media_commands_3 ( uint8_t * id , char * fn , uint8_t * wp , int cmdargc )
2021-08-28 12:18:14 +06:00
{
bool err = false ;
2022-09-18 17:17:34 -04:00
* id = atoi ( xargv [ 1 ] ) ;
if ( xargv [ 2 ] [ 0 ] = = ' \' ' | | xargv [ 2 ] [ 0 ] = = ' " ' ) {
2023-05-29 01:30:51 -04:00
for ( int curarg = 2 ; curarg < cmdargc ; curarg + + ) {
2022-09-18 17:17:34 -04:00
if ( strlen ( fn ) + strlen ( xargv [ curarg ] ) > = PATH_MAX ) {
2021-08-28 12:18:14 +06:00
err = true ;
fprintf ( stderr , " Path name too long. \n " ) ;
}
strcat ( fn , xargv [ curarg ] + ( xargv [ curarg ] [ 0 ] = = ' \' ' | | xargv [ curarg ] [ 0 ] = = ' " ' ) ) ;
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
2022-09-18 17:17:34 -04:00
| | fn [ strlen ( fn ) - 1 ] = = ' " ' ) {
if ( curarg + 1 < cmdargc ) {
2021-08-28 12:18:14 +06:00
* wp = atoi ( xargv [ curarg + 1 ] ) ;
}
break ;
}
strcat ( fn , " " ) ;
}
2022-09-18 17:17:34 -04:00
} else {
if ( strlen ( xargv [ 2 ] ) < PATH_MAX ) {
2021-08-28 12:18:14 +06:00
strcpy ( fn , xargv [ 2 ] ) ;
* wp = atoi ( xargv [ 3 ] ) ;
2022-09-18 17:17:34 -04:00
} else {
2021-08-28 12:18:14 +06:00
fprintf ( stderr , " Path name too long. \n " ) ;
err = true ;
}
}
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
2022-09-18 17:17:34 -04:00
| | fn [ strlen ( fn ) - 1 ] = = ' " ' )
fn [ strlen ( fn ) - 1 ] = ' \0 ' ;
2021-08-28 12:18:14 +06:00
return err ;
}
2022-09-18 17:17:34 -04:00
char * ( * f_readline ) ( const char * ) = NULL ;
int ( * f_add_history ) ( const char * ) = NULL ;
2021-08-28 14:59:12 +06:00
void ( * f_rl_callback_handler_remove ) ( void ) = NULL ;
2021-08-28 13:56:23 +06:00
# ifdef __APPLE__
2022-09-18 17:17:34 -04:00
# define LIBEDIT_LIBRARY "libedit.dylib"
2021-08-28 13:56:23 +06:00
# else
2022-09-18 17:17:34 -04:00
# define LIBEDIT_LIBRARY "libedit.so"
2021-08-28 13:56:23 +06:00
# endif
2022-09-18 17:17:34 -04:00
uint32_t
timer_onesec ( uint32_t interval , void * param )
2021-08-29 00:53:18 +06:00
{
2022-09-18 17:17:34 -04:00
pc_onesec ( ) ;
return interval ;
2021-08-29 00:53:18 +06:00
}
2021-08-28 12:18:14 +06:00
2022-09-18 17:17:34 -04:00
void
monitor_thread ( void * param )
2021-08-25 15:17:46 +06:00
{
2021-08-30 00:41:40 +06:00
# ifndef USE_CLI
2022-09-18 17:17:34 -04:00
if ( isatty ( fileno ( stdin ) ) & & isatty ( fileno ( stdout ) ) ) {
char * line = NULL ;
2021-08-25 15:34:40 +06:00
size_t n ;
2021-08-25 15:17:46 +06:00
printf ( " 86Box monitor console. \n " ) ;
2022-09-18 17:17:34 -04:00
while ( ! exit_event ) {
if ( feof ( stdin ) )
break ;
2021-08-28 13:56:23 +06:00
if ( f_readline )
line = f_readline ( " (86Box) " ) ;
2022-09-18 17:17:34 -04:00
else {
2021-08-28 13:56:23 +06:00
printf ( " (86Box) " ) ;
getline ( & line , & n , stdin ) ;
}
2022-09-18 17:17:34 -04:00
if ( line ) {
int cmdargc = 0 ;
char * linecpy ;
2021-08-25 22:34:58 +06:00
line [ strcspn ( line , " \r \n " ) ] = ' \0 ' ;
2022-09-18 17:17:34 -04:00
linecpy = strdup ( line ) ;
if ( ! linecpy ) {
2021-08-25 22:34:58 +06:00
free ( line ) ;
line = NULL ;
continue ;
}
2022-09-18 17:17:34 -04:00
if ( f_add_history )
f_add_history ( line ) ;
2021-08-25 22:34:58 +06:00
memset ( xargv , 0 , sizeof ( xargv ) ) ;
2022-09-18 17:17:34 -04:00
while ( 1 ) {
2021-08-25 22:34:58 +06:00
xargv [ cmdargc + + ] = local_strsep ( & linecpy , " " ) ;
2022-09-18 17:17:34 -04:00
if ( xargv [ cmdargc - 1 ] = = NULL | | cmdargc > = 512 )
break ;
2021-08-25 22:34:58 +06:00
}
2021-09-08 13:49:04 +06:00
cmdargc - - ;
2022-09-18 17:17:34 -04:00
if ( strncasecmp ( xargv [ 0 ] , " help " , 4 ) = = 0 ) {
2021-09-08 13:49:04 +06:00
printf (
" fddload <id> <filename> <wp> - Load floppy disk image into drive <id>. \n "
" cdload <id> <filename> - Load CD-ROM image into drive <id>. \n "
" zipload <id> <filename> <wp> - Load ZIP image into ZIP drive <id>. \n "
" cartload <id> <filename> <wp> - Load cartridge image into cartridge drive <id>. \n "
" moload <id> <filename> <wp> - Load MO image into MO drive <id>. \n \n "
" fddeject <id> - eject disk from floppy drive <id>. \n "
" cdeject <id> - eject disc from CD-ROM drive <id>. \n "
" zipeject <id> - eject ZIP image from ZIP drive <id>. \n "
" carteject <id> - eject cartridge from drive <id>. \n "
" moeject <id> - eject image from MO drive <id>. \n \n "
" hardreset - hard reset the emulated system. \n "
" pause - pause the the emulated system. \n "
" fullscreen - toggle fullscreen. \n "
2023-06-29 20:41:36 +05:00
" version - print version and license information. \n "
2021-09-08 13:49:04 +06:00
" exit - exit 86Box. \n " ) ;
2022-09-18 17:17:34 -04:00
} else if ( strncasecmp ( xargv [ 0 ] , " exit " , 4 ) = = 0 ) {
2021-08-25 15:34:40 +06:00
exit_event = 1 ;
2023-06-29 20:41:36 +05:00
} else if ( strncasecmp ( xargv [ 0 ] , " version " , 7 ) = = 0 ) {
# ifndef EMU_GIT_HASH
# define EMU_GIT_HASH "0000000"
# endif
# if defined(__arm__) || defined(__TARGET_ARCH_ARM)
# define ARCH_STR "arm"
# elif defined(__aarch64__) || defined(_M_ARM64)
# define ARCH_STR "arm64"
# elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
# define ARCH_STR "i386"
# elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
# define ARCH_STR "x86_64"
# else
# define ARCH_STR "unknown arch"
# endif
# ifdef USE_DYNAREC
# ifdef USE_NEW_DYNAREC
# define DYNAREC_STR "new dynarec"
# else
# define DYNAREC_STR "old dynarec"
# endif
# else
# define DYNAREC_STR "no dynarec"
# endif
printf (
" %s v%s [%s] [%s, %s] \n \n "
" An emulator of old computers \n "
2023-08-26 21:33:56 +05:00
" Authors: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), "
" Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), "
" Tiseno100, reenigne, and others. \n "
" With previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others. \n \n "
2023-06-29 20:41:36 +05:00
" Released under the GNU General Public License version 2 or later. See LICENSE for more information. \n " ,
EMU_NAME , EMU_VERSION_FULL , EMU_GIT_HASH , ARCH_STR , DYNAREC_STR ) ;
2022-09-18 17:17:34 -04:00
} else if ( strncasecmp ( xargv [ 0 ] , " fullscreen " , 10 ) = = 0 ) {
video_fullscreen = video_fullscreen ? 0 : 1 ;
2021-08-29 15:41:06 +06:00
fullscreen_pending = 1 ;
2022-09-18 17:17:34 -04:00
} else if ( strncasecmp ( xargv [ 0 ] , " pause " , 5 ) = = 0 ) {
2021-08-28 00:45:35 +06:00
plat_pause ( dopause ^ 1 ) ;
2021-08-28 12:18:14 +06:00
printf ( " %s " , dopause ? " Paused. \n " : " Unpaused. \n " ) ;
2022-09-18 17:17:34 -04:00
} else if ( strncasecmp ( xargv [ 0 ] , " hardreset " , 9 ) = = 0 ) {
2021-08-26 17:09:39 +06:00
pc_reset_hard ( ) ;
2022-09-18 17:17:34 -04:00
} else if ( strncasecmp ( xargv [ 0 ] , " cdload " , 6 ) = = 0 & & cmdargc > = 3 ) {
2021-08-26 17:09:39 +06:00
uint8_t id ;
2022-09-18 17:17:34 -04:00
bool err = false ;
char fn [ PATH_MAX ] ;
2022-02-20 02:26:27 -05:00
2022-09-18 17:17:34 -04:00
if ( ! xargv [ 2 ] | | ! xargv [ 1 ] ) {
2021-08-26 17:41:55 +06:00
free ( line ) ;
free ( linecpy ) ;
line = NULL ;
continue ;
}
2021-08-26 17:09:39 +06:00
id = atoi ( xargv [ 1 ] ) ;
memset ( fn , 0 , sizeof ( fn ) ) ;
2022-09-18 17:17:34 -04:00
if ( xargv [ 2 ] [ 0 ] = = ' \' ' | | xargv [ 2 ] [ 0 ] = = ' " ' ) {
2021-08-26 17:09:39 +06:00
int curarg = 2 ;
2022-09-18 17:17:34 -04:00
for ( curarg = 2 ; curarg < cmdargc ; curarg + + ) {
if ( strlen ( fn ) + strlen ( xargv [ curarg ] ) > = PATH_MAX ) {
2021-08-26 17:09:39 +06:00
err = true ;
fprintf ( stderr , " Path name too long. \n " ) ;
}
strcat ( fn , xargv [ curarg ] + ( xargv [ curarg ] [ 0 ] = = ' \' ' | | xargv [ curarg ] [ 0 ] = = ' " ' ) ) ;
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
2022-09-18 17:17:34 -04:00
| | fn [ strlen ( fn ) - 1 ] = = ' " ' ) {
2021-08-26 17:09:39 +06:00
break ;
}
strcat ( fn , " " ) ;
}
2022-09-18 17:17:34 -04:00
} else {
if ( strlen ( xargv [ 2 ] ) < PATH_MAX ) {
2021-08-26 17:09:39 +06:00
strcpy ( fn , xargv [ 2 ] ) ;
2022-09-18 17:17:34 -04:00
} else {
2021-08-26 17:09:39 +06:00
fprintf ( stderr , " Path name too long. \n " ) ;
}
}
2022-09-18 17:17:34 -04:00
if ( ! err ) {
2021-08-26 17:09:39 +06:00
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
2022-09-18 17:17:34 -04:00
| | fn [ strlen ( fn ) - 1 ] = = ' " ' )
fn [ strlen ( fn ) - 1 ] = ' \0 ' ;
2021-08-27 01:11:52 +06:00
printf ( " Inserting disc into CD-ROM drive %hhu: %s \n " , id , fn ) ;
2021-08-26 17:09:39 +06:00
cdrom_mount ( id , fn ) ;
}
2022-09-18 17:17:34 -04:00
} else if ( strncasecmp ( xargv [ 0 ] , " fddeject " , 8 ) = = 0 & & cmdargc > = 2 ) {
2021-08-28 23:06:07 +06:00
floppy_eject ( atoi ( xargv [ 1 ] ) ) ;
2022-09-18 17:17:34 -04:00
} else if ( strncasecmp ( xargv [ 0 ] , " cdeject " , 8 ) = = 0 & & cmdargc > = 2 ) {
2021-08-28 23:06:07 +06:00
cdrom_mount ( atoi ( xargv [ 1 ] ) , " " ) ;
2022-09-18 17:17:34 -04:00
} else if ( strncasecmp ( xargv [ 0 ] , " moeject " , 8 ) = = 0 & & cmdargc > = 2 ) {
2021-08-28 23:06:07 +06:00
mo_eject ( atoi ( xargv [ 1 ] ) ) ;
2022-09-18 17:17:34 -04:00
} else if ( strncasecmp ( xargv [ 0 ] , " carteject " , 8 ) = = 0 & & cmdargc > = 2 ) {
2021-08-28 23:06:07 +06:00
cartridge_eject ( atoi ( xargv [ 1 ] ) ) ;
2022-09-18 17:17:34 -04:00
} else if ( strncasecmp ( xargv [ 0 ] , " zipeject " , 8 ) = = 0 & & cmdargc > = 2 ) {
2021-08-28 23:06:07 +06:00
zip_eject ( atoi ( xargv [ 1 ] ) ) ;
2022-09-18 17:17:34 -04:00
} else if ( strncasecmp ( xargv [ 0 ] , " fddload " , 7 ) = = 0 & & cmdargc > = 4 ) {
2023-05-29 01:30:51 -04:00
uint8_t id ;
uint8_t wp ;
2022-09-18 17:17:34 -04:00
bool err = false ;
char fn [ PATH_MAX ] ;
2021-08-25 22:34:58 +06:00
memset ( fn , 0 , sizeof ( fn ) ) ;
2022-09-18 17:17:34 -04:00
if ( ! xargv [ 2 ] | | ! xargv [ 1 ] ) {
2021-08-26 17:41:55 +06:00
free ( line ) ;
free ( linecpy ) ;
line = NULL ;
continue ;
}
2021-08-28 12:18:14 +06:00
err = process_media_commands_3 ( & id , fn , & wp , cmdargc ) ;
2022-09-18 17:17:34 -04:00
if ( ! err ) {
2021-08-28 12:18:14 +06:00
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
2022-09-18 17:17:34 -04:00
| | fn [ strlen ( fn ) - 1 ] = = ' " ' )
fn [ strlen ( fn ) - 1 ] = ' \0 ' ;
2021-08-28 12:18:14 +06:00
printf ( " Inserting disk into floppy drive %c: %s \n " , id + ' A ' , fn ) ;
floppy_mount ( id , fn , wp ) ;
2021-08-25 22:34:58 +06:00
}
2022-09-18 17:17:34 -04:00
} else if ( strncasecmp ( xargv [ 0 ] , " moload " , 7 ) = = 0 & & cmdargc > = 4 ) {
2023-05-29 01:30:51 -04:00
uint8_t id ;
uint8_t wp ;
2022-09-18 17:17:34 -04:00
bool err = false ;
char fn [ PATH_MAX ] ;
2021-08-28 12:18:14 +06:00
memset ( fn , 0 , sizeof ( fn ) ) ;
2022-09-18 17:17:34 -04:00
if ( ! xargv [ 2 ] | | ! xargv [ 1 ] ) {
2021-08-28 12:18:14 +06:00
free ( line ) ;
free ( linecpy ) ;
line = NULL ;
continue ;
2021-08-25 22:34:58 +06:00
}
2021-08-28 12:18:14 +06:00
err = process_media_commands_3 ( & id , fn , & wp , cmdargc ) ;
2022-09-18 17:17:34 -04:00
if ( ! err ) {
2021-08-26 17:09:39 +06:00
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
2022-09-18 17:17:34 -04:00
| | fn [ strlen ( fn ) - 1 ] = = ' " ' )
fn [ strlen ( fn ) - 1 ] = ' \0 ' ;
2021-08-28 12:18:14 +06:00
printf ( " Inserting into mo drive %hhu: %s \n " , id , fn ) ;
mo_mount ( id , fn , wp ) ;
}
2022-09-18 17:17:34 -04:00
} else if ( strncasecmp ( xargv [ 0 ] , " cartload " , 7 ) = = 0 & & cmdargc > = 4 ) {
2023-05-29 01:30:51 -04:00
uint8_t id ;
uint8_t wp ;
2022-09-18 17:17:34 -04:00
bool err = false ;
char fn [ PATH_MAX ] ;
2021-08-28 12:18:14 +06:00
memset ( fn , 0 , sizeof ( fn ) ) ;
2022-09-18 17:17:34 -04:00
if ( ! xargv [ 2 ] | | ! xargv [ 1 ] ) {
2021-08-28 12:18:14 +06:00
free ( line ) ;
free ( linecpy ) ;
line = NULL ;
continue ;
}
err = process_media_commands_3 ( & id , fn , & wp , cmdargc ) ;
2022-09-18 17:17:34 -04:00
if ( ! err ) {
2021-08-28 12:18:14 +06:00
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
2022-09-18 17:17:34 -04:00
| | fn [ strlen ( fn ) - 1 ] = = ' " ' )
fn [ strlen ( fn ) - 1 ] = ' \0 ' ;
2021-08-28 12:18:14 +06:00
printf ( " Inserting tape into cartridge holder %hhu: %s \n " , id , fn ) ;
cartridge_mount ( id , fn , wp ) ;
}
2022-09-18 17:17:34 -04:00
} else if ( strncasecmp ( xargv [ 0 ] , " zipload " , 7 ) = = 0 & & cmdargc > = 4 ) {
2023-05-29 01:30:51 -04:00
uint8_t id ;
uint8_t wp ;
2022-09-18 17:17:34 -04:00
bool err = false ;
char fn [ PATH_MAX ] ;
2021-08-28 12:18:14 +06:00
memset ( fn , 0 , sizeof ( fn ) ) ;
2022-09-18 17:17:34 -04:00
if ( ! xargv [ 2 ] | | ! xargv [ 1 ] ) {
2021-08-28 12:18:14 +06:00
free ( line ) ;
free ( linecpy ) ;
line = NULL ;
continue ;
}
err = process_media_commands_3 ( & id , fn , & wp , cmdargc ) ;
2022-09-18 17:17:34 -04:00
if ( ! err ) {
2021-08-28 12:18:14 +06:00
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
2022-09-18 17:17:34 -04:00
| | fn [ strlen ( fn ) - 1 ] = = ' " ' )
fn [ strlen ( fn ) - 1 ] = ' \0 ' ;
2021-08-28 12:18:14 +06:00
printf ( " Inserting disk into ZIP drive %c: %s \n " , id + ' A ' , fn ) ;
zip_mount ( id , fn , wp ) ;
2021-08-25 22:34:58 +06:00
}
2021-08-25 15:34:40 +06:00
}
free ( line ) ;
2021-08-25 22:34:58 +06:00
free ( linecpy ) ;
line = NULL ;
2021-08-25 15:34:40 +06:00
}
}
2021-08-25 15:17:46 +06:00
}
2021-08-30 00:41:40 +06:00
# endif
2021-08-25 15:17:46 +06:00
}
2021-08-29 15:41:06 +06:00
2023-02-06 04:12:46 -05:00
extern int gfxcard [ 2 ] ;
2022-09-18 17:17:34 -04:00
int
main ( int argc , char * * argv )
2021-08-22 16:32:52 +06:00
{
SDL_Event event ;
2022-09-18 17:17:34 -04:00
void * libedithandle ;
2021-08-22 16:32:52 +06:00
SDL_Init ( 0 ) ;
pc_init ( argc , argv ) ;
2022-09-18 17:17:34 -04:00
if ( ! pc_init_modules ( ) ) {
2021-10-13 23:41:02 +06:00
ui_msgbox_header ( MBX_FATAL , L " No ROMs found. " , L " 86Box could not find any usable ROM images. \n \n Please download a ROM set and extract it into the \" roms \" directory. " ) ;
2021-08-22 16:32:52 +06:00
SDL_Quit ( ) ;
return 6 ;
}
2022-02-20 02:26:27 -05:00
2023-02-28 23:24:58 -05:00
gfxcard [ 1 ] = 0 ;
2021-08-26 00:15:42 +06:00
eventthread = SDL_ThreadID ( ) ;
2022-09-18 17:17:34 -04:00
blitmtx = SDL_CreateMutex ( ) ;
if ( ! blitmtx ) {
2021-08-22 16:32:52 +06:00
fprintf ( stderr , " Failed to create blit mutex: %s " , SDL_GetError ( ) ) ;
return - 1 ;
}
2021-08-28 23:06:07 +06:00
libedithandle = dlopen ( LIBEDIT_LIBRARY , RTLD_LOCAL | RTLD_LAZY ) ;
2022-09-18 17:17:34 -04:00
if ( libedithandle ) {
f_readline = dlsym ( libedithandle , " readline " ) ;
2021-08-28 23:06:07 +06:00
f_add_history = dlsym ( libedithandle , " add_history " ) ;
2022-09-18 17:17:34 -04:00
if ( ! f_readline ) {
2021-08-28 23:06:07 +06:00
fprintf ( stderr , " readline in libedit not found, line editing will be limited. \n " ) ;
}
f_rl_callback_handler_remove = dlsym ( libedithandle , " rl_callback_handler_remove " ) ;
2022-09-18 17:17:34 -04:00
} else
fprintf ( stderr , " libedit not found, line editing will be limited. \n " ) ;
2021-08-23 16:38:55 +06:00
mousemutex = SDL_CreateMutex ( ) ;
2021-08-22 16:32:52 +06:00
sdl_initho ( ) ;
2022-09-18 17:17:34 -04:00
if ( start_in_fullscreen ) {
2021-08-29 15:41:06 +06:00
video_fullscreen = 1 ;
2022-09-18 17:17:34 -04:00
sdl_set_fs ( 1 ) ;
2021-08-29 15:41:06 +06:00
}
2021-08-22 16:32:52 +06:00
/* Fire up the machine. */
pc_reset_hard_init ( ) ;
/* Set the PAUSE mode depending on the renderer. */
2022-09-18 17:17:34 -04:00
// plat_pause(0);
2021-08-22 16:32:52 +06:00
/* Initialize the rendering window, or fullscreen. */
do_start ( ) ;
2021-08-30 00:41:40 +06:00
# ifndef USE_CLI
2021-08-25 15:34:40 +06:00
thread_create ( monitor_thread , NULL ) ;
2021-08-30 00:41:40 +06:00
# endif
2021-08-29 00:53:18 +06:00
SDL_AddTimer ( 1000 , timer_onesec , NULL ) ;
2022-09-18 17:17:34 -04:00
while ( ! is_quit ) {
2021-09-20 16:25:25 +06:00
static int mouse_inside = 0 ;
2022-09-18 17:17:34 -04:00
while ( SDL_PollEvent ( & event ) ) {
switch ( event . type ) {
2021-08-29 00:34:03 +06:00
case SDL_QUIT :
exit_event = 1 ;
break ;
case SDL_MOUSEWHEEL :
2021-08-23 15:56:24 +06:00
{
2022-09-18 17:17:34 -04:00
if ( mouse_capture | | video_fullscreen ) {
if ( event . wheel . direction = = SDL_MOUSEWHEEL_FLIPPED ) {
event . wheel . x * = - 1 ;
event . wheel . y * = - 1 ;
}
SDL_LockMutex ( mousemutex ) ;
2023-08-07 18:49:58 +02:00
mouse_set_z ( event . wheel . y ) ;
2022-09-18 17:17:34 -04:00
SDL_UnlockMutex ( mousemutex ) ;
2021-08-29 00:34:03 +06:00
}
2022-09-18 17:17:34 -04:00
break ;
2021-08-23 15:56:24 +06:00
}
2021-08-29 00:34:03 +06:00
case SDL_MOUSEMOTION :
{
2022-09-18 17:17:34 -04:00
if ( mouse_capture | | video_fullscreen ) {
SDL_LockMutex ( mousemutex ) ;
2023-08-07 18:49:58 +02:00
mouse_scale ( event . motion . xrel , event . motion . yrel ) ;
2022-09-18 17:17:34 -04:00
SDL_UnlockMutex ( mousemutex ) ;
}
break ;
2021-08-29 00:34:03 +06:00
}
case SDL_MOUSEBUTTONDOWN :
case SDL_MOUSEBUTTONUP :
{
2022-09-18 17:17:34 -04:00
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 ;
2021-08-29 00:34:03 +06:00
}
2022-09-18 17:17:34 -04:00
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 ;
2022-10-28 23:51:38 +06:00
case SDL_BUTTON_X1 :
buttonmask = 8 ;
break ;
case SDL_BUTTON_X2 :
buttonmask = 16 ;
break ;
2022-09-18 17:17:34 -04:00
}
SDL_LockMutex ( mousemutex ) ;
2023-08-07 18:49:58 +02:00
if ( event . button . state = = SDL_PRESSED )
mouse_set_buttons_ex ( mouse_get_buttons_ex ( ) | buttonmask ) ;
else
mouse_set_buttons_ex ( mouse_get_buttons_ex ( ) & ~ buttonmask ) ;
2022-09-18 17:17:34 -04:00
SDL_UnlockMutex ( mousemutex ) ;
2021-08-29 00:34:03 +06:00
}
2022-09-18 17:17:34 -04:00
break ;
2021-08-23 15:56:24 +06:00
}
2021-08-29 00:34:03 +06:00
case SDL_RENDER_DEVICE_RESET :
case SDL_RENDER_TARGETS_RESET :
2022-02-20 02:26:27 -05:00
{
2022-12-19 19:45:39 -05:00
extern void sdl_reinit_texture ( void ) ;
2021-08-29 00:34:03 +06:00
sdl_reinit_texture ( ) ;
2021-08-23 00:47:07 +06:00
break ;
2021-08-29 00:34:03 +06:00
}
case SDL_KEYDOWN :
case SDL_KEYUP :
{
2022-09-18 17:17:34 -04:00
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 ) ;
2021-08-29 00:34:03 +06:00
}
2021-09-20 16:25:25 +06:00
case SDL_WINDOWEVENT :
{
2022-09-18 17:17:34 -04:00
switch ( event . window . event ) {
case SDL_WINDOWEVENT_ENTER :
mouse_inside = 1 ;
break ;
case SDL_WINDOWEVENT_LEAVE :
mouse_inside = 0 ;
break ;
}
2021-09-20 16:25:25 +06:00
}
2021-08-23 00:47:07 +06:00
}
2022-09-18 17:17:34 -04:00
}
if ( mouse_capture & & keyboard_ismsexit ( ) ) {
2021-08-23 15:56:24 +06:00
plat_mouse_capture ( 0 ) ;
2022-02-20 02:26:27 -05:00
}
2022-09-18 17:17:34 -04:00
if ( blitreq ) {
2021-09-13 23:19:10 +02:00
extern void sdl_blit ( int x , int y , int w , int h ) ;
sdl_blit ( params . x , params . y , params . w , params . h ) ;
2021-08-22 16:32:52 +06:00
}
2022-09-18 17:17:34 -04:00
if ( title_set ) {
2022-12-19 19:45:39 -05:00
extern void ui_window_title_real ( void ) ;
2021-08-26 00:15:42 +06:00
ui_window_title_real ( ) ;
2021-08-23 14:09:43 +06:00
}
2022-09-18 17:17:34 -04:00
if ( video_fullscreen & & keyboard_isfsexit ( ) ) {
2021-08-29 15:41:06 +06:00
sdl_set_fs ( 0 ) ;
video_fullscreen = 0 ;
}
2022-09-18 17:17:34 -04:00
if ( fullscreen_pending ) {
2021-08-29 15:41:06 +06:00
sdl_set_fs ( video_fullscreen ) ;
fullscreen_pending = 0 ;
}
2022-09-18 17:17:34 -04:00
if ( exit_event ) {
2021-08-25 00:09:02 +06:00
do_stop ( ) ;
break ;
}
2021-08-22 16:32:52 +06:00
}
2021-08-26 17:09:39 +06:00
printf ( " \n " ) ;
2021-08-22 16:32:52 +06:00
SDL_DestroyMutex ( blitmtx ) ;
2021-08-29 00:53:18 +06:00
SDL_DestroyMutex ( mousemutex ) ;
2021-08-22 16:32:52 +06:00
SDL_Quit ( ) ;
2022-09-18 17:17:34 -04:00
if ( f_rl_callback_handler_remove )
f_rl_callback_handler_remove ( ) ;
2021-08-22 16:32:52 +06:00
return 0 ;
}
2022-09-18 17:17:34 -04:00
char *
plat_vidapi_name ( int i )
2021-08-22 16:32:52 +06:00
{
return " default " ;
}
2021-11-09 18:53:15 +01:00
2021-11-09 22:33:54 +01:00
void
set_language ( uint32_t id )
{
lang_id = id ;
}
2021-11-09 18:53:15 +01:00
/* Sets up the program language before initialization. */
2022-09-18 17:17:34 -04:00
uint32_t
plat_language_code ( char * langcode )
2021-11-09 18:53:15 +01:00
{
2022-02-20 02:26:27 -05:00
/* or maybe not */
2021-11-09 18:53:15 +01:00
return 0 ;
}
2023-08-09 17:12:27 -04:00
void
plat_get_cpu_string ( char * outbuf , uint8_t len ) {
char cpu_string [ ] = " Unknown " ;
strncpy ( outbuf , cpu_string , len ) ;
}
2021-11-14 15:00:55 +01:00
/* Converts back the language code to LCID */
void
2022-09-18 17:17:34 -04:00
plat_language_code_r ( uint32_t lcid , char * outbuf , int len )
2021-11-14 15:00:55 +01:00
{
2022-02-20 02:26:27 -05:00
/* or maybe not */
2021-11-14 15:00:55 +01:00
return ;
}
2022-09-18 17:17:34 -04:00
void
joystick_init ( void )
{
}
void
joystick_close ( void )
{
}
void
joystick_process ( void )
{
}
void
2022-12-19 19:45:39 -05:00
startblit ( void )
2021-08-22 16:32:52 +06:00
{
SDL_LockMutex ( blitmtx ) ;
}
2022-09-18 17:17:34 -04:00
void
2022-12-19 19:45:39 -05:00
endblit ( void )
2021-08-22 16:32:52 +06:00
{
SDL_UnlockMutex ( blitmtx ) ;
2021-08-25 02:01:39 +06:00
}
2022-02-07 22:58:08 +01:00
/* API */
void
2022-09-18 17:17:34 -04:00
ui_sb_mt32lcd ( char * str )
2022-02-07 22:58:08 +01:00
{
2022-02-18 21:42:05 +01:00
}
2023-01-03 15:42:57 +06:00
void
ui_hard_reset_completed ( void )
{
}