2021-08-22 16:32:52 +06:00
# ifdef __linux__
# define _FILE_OFFSET_BITS 64
# define _LARGEFILE64_SOURCE 1
# endif
2021-08-25 15:34:40 +06:00
# define _POSIX_C_SOURCE 200809L
2021-08-25 20:15:19 +06:00
# ifdef __APPLE__
# define _DARWIN_C_SOURCE 1
# endif
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>
# include <unistd.h>
# include <errno.h>
# include <inttypes.h>
# include <dlfcn.h>
2021-08-29 00:53:18 +06:00
# include <wchar.h>
2021-08-25 02:01:39 +06:00
# include <SDL.h>
2021-08-22 16:32:52 +06:00
# include <86box/86box.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>
# include <86box/plat.h>
# include <86box/plat_dynld.h>
# include <86box/device.h>
# include <86box/gameport.h>
# include <86box/unix_sdl.h>
# include <86box/timer.h>
# include <86box/nvr.h>
2021-08-28 00:37:09 +06:00
# include <86box/ui.h>
2021-08-23 14:09:43 +06:00
2021-08-22 16:32:52 +06:00
static int first_use = 1 ;
static uint64_t StartingTime ;
static uint64_t Frequency ;
int rctrl_is_lalt ;
int update_icons ;
int kbd_req_capture ;
int hide_status_bar ;
int fixed_size_x = 640 ;
int fixed_size_y = 480 ;
2021-08-26 00:15:42 +06:00
extern int title_set ;
extern wchar_t sdl_win_title [ 512 ] ;
2021-08-22 16:32:52 +06:00
plat_joystick_t plat_joystick_state [ MAX_PLAT_JOYSTICKS ] ;
joystick_t joystick_state [ MAX_JOYSTICKS ] ;
int joysticks_present ;
SDL_mutex * blitmtx ;
2021-08-29 15:41:06 +06:00
SDL_threadID eventthread ;
static int exit_event = 0 ;
static int fullscreen_pending = 0 ;
2021-08-22 16:32:52 +06:00
2021-08-23 00:47:07 +06:00
static const uint16_t sdl_to_xt [ 0x200 ] =
{
[ SDL_SCANCODE_ESCAPE ] = 0x01 ,
[ SDL_SCANCODE_1 ] = 0x02 ,
[ SDL_SCANCODE_2 ] = 0x03 ,
[ SDL_SCANCODE_3 ] = 0x04 ,
[ SDL_SCANCODE_4 ] = 0x05 ,
[ SDL_SCANCODE_5 ] = 0x06 ,
[ SDL_SCANCODE_6 ] = 0x07 ,
[ SDL_SCANCODE_7 ] = 0x08 ,
[ SDL_SCANCODE_8 ] = 0x09 ,
[ SDL_SCANCODE_9 ] = 0x0A ,
[ SDL_SCANCODE_0 ] = 0x0B ,
[ SDL_SCANCODE_MINUS ] = 0x0C ,
[ SDL_SCANCODE_EQUALS ] = 0x0D ,
[ SDL_SCANCODE_BACKSPACE ] = 0x0E ,
[ SDL_SCANCODE_TAB ] = 0x0F ,
[ SDL_SCANCODE_Q ] = 0x10 ,
[ SDL_SCANCODE_W ] = 0x11 ,
[ SDL_SCANCODE_E ] = 0x12 ,
[ SDL_SCANCODE_R ] = 0x13 ,
[ SDL_SCANCODE_T ] = 0x14 ,
[ SDL_SCANCODE_Y ] = 0x15 ,
[ SDL_SCANCODE_U ] = 0x16 ,
[ SDL_SCANCODE_I ] = 0x17 ,
[ SDL_SCANCODE_O ] = 0x18 ,
[ SDL_SCANCODE_P ] = 0x19 ,
[ SDL_SCANCODE_LEFTBRACKET ] = 0x1A ,
[ SDL_SCANCODE_RIGHTBRACKET ] = 0x1B ,
[ SDL_SCANCODE_RETURN ] = 0x1C ,
[ SDL_SCANCODE_LCTRL ] = 0x1D ,
[ SDL_SCANCODE_A ] = 0x1E ,
[ SDL_SCANCODE_S ] = 0x1F ,
[ SDL_SCANCODE_D ] = 0x20 ,
[ SDL_SCANCODE_F ] = 0x21 ,
[ SDL_SCANCODE_G ] = 0x22 ,
[ SDL_SCANCODE_H ] = 0x23 ,
[ SDL_SCANCODE_J ] = 0x24 ,
[ SDL_SCANCODE_K ] = 0x25 ,
[ SDL_SCANCODE_L ] = 0x26 ,
[ SDL_SCANCODE_SEMICOLON ] = 0x27 ,
[ SDL_SCANCODE_APOSTROPHE ] = 0x28 ,
[ SDL_SCANCODE_GRAVE ] = 0x29 ,
[ SDL_SCANCODE_LSHIFT ] = 0x2A ,
[ SDL_SCANCODE_BACKSLASH ] = 0x2B ,
[ SDL_SCANCODE_Z ] = 0x2C ,
[ SDL_SCANCODE_X ] = 0x2D ,
[ SDL_SCANCODE_C ] = 0x2E ,
[ SDL_SCANCODE_V ] = 0x2F ,
[ SDL_SCANCODE_B ] = 0x30 ,
[ SDL_SCANCODE_N ] = 0x31 ,
[ SDL_SCANCODE_M ] = 0x32 ,
[ SDL_SCANCODE_COMMA ] = 0x33 ,
[ SDL_SCANCODE_PERIOD ] = 0x34 ,
[ SDL_SCANCODE_SLASH ] = 0x35 ,
[ SDL_SCANCODE_RSHIFT ] = 0x36 ,
[ SDL_SCANCODE_KP_MULTIPLY ] = 0x37 ,
[ SDL_SCANCODE_LALT ] = 0x38 ,
[ SDL_SCANCODE_SPACE ] = 0x39 ,
[ SDL_SCANCODE_CAPSLOCK ] = 0x3A ,
[ SDL_SCANCODE_F1 ] = 0x3B ,
[ SDL_SCANCODE_F2 ] = 0x3C ,
[ SDL_SCANCODE_F3 ] = 0x3D ,
[ SDL_SCANCODE_F4 ] = 0x3E ,
[ SDL_SCANCODE_F5 ] = 0x3F ,
[ SDL_SCANCODE_F6 ] = 0x40 ,
[ SDL_SCANCODE_F7 ] = 0x41 ,
[ SDL_SCANCODE_F8 ] = 0x42 ,
[ SDL_SCANCODE_F9 ] = 0x43 ,
[ SDL_SCANCODE_F10 ] = 0x44 ,
[ SDL_SCANCODE_NUMLOCKCLEAR ] = 0x45 ,
[ SDL_SCANCODE_SCROLLLOCK ] = 0x46 ,
2021-08-25 00:09:02 +06:00
[ SDL_SCANCODE_HOME ] = 0x147 ,
[ SDL_SCANCODE_UP ] = 0x148 ,
[ SDL_SCANCODE_PAGEUP ] = 0x149 ,
2021-08-23 00:47:07 +06:00
[ SDL_SCANCODE_KP_MINUS ] = 0x4A ,
2021-08-25 00:09:02 +06:00
[ SDL_SCANCODE_LEFT ] = 0x14B ,
2021-08-23 00:47:07 +06:00
[ SDL_SCANCODE_KP_5 ] = 0x4C ,
2021-08-25 00:09:02 +06:00
[ SDL_SCANCODE_RIGHT ] = 0x14D ,
2021-08-23 00:47:07 +06:00
[ SDL_SCANCODE_KP_PLUS ] = 0x4E ,
2021-08-25 00:09:02 +06:00
[ SDL_SCANCODE_END ] = 0x14F ,
[ SDL_SCANCODE_DOWN ] = 0x150 ,
[ SDL_SCANCODE_PAGEDOWN ] = 0x151 ,
[ SDL_SCANCODE_INSERT ] = 0x152 ,
[ SDL_SCANCODE_DELETE ] = 0x153 ,
2021-08-23 00:47:07 +06:00
[ SDL_SCANCODE_F11 ] = 0x57 ,
[ SDL_SCANCODE_F12 ] = 0x58 ,
[ SDL_SCANCODE_KP_ENTER ] = 0x11c ,
[ SDL_SCANCODE_RCTRL ] = 0x11d ,
[ SDL_SCANCODE_KP_DIVIDE ] = 0x135 ,
2021-08-23 01:17:56 +06: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 ,
2021-08-23 17:26:04 +06:00
[ SDL_SCANCODE_KP_1 ] = 0x4F ,
2021-08-28 14:59:12 +06:00
[ SDL_SCANCODE_KP_0 ] = 0x52 ,
[ SDL_SCANCODE_KP_PERIOD ] = 0x53
2021-08-23 00:47:07 +06:00
} ;
2021-08-22 16:32:52 +06:00
typedef struct sdl_blit_params
{
int x , y , y1 , y2 , w , h ;
} sdl_blit_params ;
sdl_blit_params params = { 0 , 0 , 0 , 0 , 0 , 0 } ;
int blitreq = 0 ;
void * dynld_module ( const char * name , dllimp_t * table )
{
dllimp_t * imp ;
void * modhandle = dlopen ( name , RTLD_LAZY | RTLD_GLOBAL ) ;
if ( modhandle )
{
for ( imp = table ; imp - > name ! = NULL ; imp + + )
{
2021-08-22 20:34:19 +06:00
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 )
{
struct tm * calendertime ;
struct timeval t ;
time_t curtime ;
if ( prefix ! = NULL )
sprintf ( bufp , " %s- " , prefix ) ;
else
strcpy ( bufp , " " ) ;
gettimeofday ( & t , NULL ) ;
curtime = time ( NULL ) ;
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
plat_chdir ( char * str )
{
return chdir ( str ) ;
}
void dynld_close ( void * handle )
{
dlclose ( handle ) ;
}
wchar_t * plat_get_string ( int i )
{
2021-08-23 14:09:43 +06:00
switch ( i )
{
case IDS_2077 :
return L " Click to capture mouse. " ;
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 " ;
2021-08-28 00:37:09 +06:00
case IDS_2080 :
return L " Failed to initialize FluidSynth " ;
case IDS_4099 :
return L " MFM/RLL or ESDI CD-ROM drives never existed " ;
case IDS_2093 :
return L " Failed to set up PCap " ;
case IDS_2094 :
return L " No PCap devices found " ;
case IDS_2110 :
return L " Unable to initialize FreeType " ;
case IDS_2111 :
return L " Unable to initialize SDL, libsdl2 is required " ;
case IDS_2131 :
return L " libfreetype is required for ESC/P printer emulation. " ;
case IDS_2132 :
return L " libgs is required for automatic conversion of PostScript files to PDF. \n \n Any documents sent to the generic PostScript printer will be saved as PostScript (.ps) files. " ;
case IDS_2129 :
return L " Make sure libpcap is installed and that you are on a libpcap-compatible network connection. " ;
case IDS_2114 :
return L " Unable to initialize Ghostscript " ;
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
plat_path_abs ( char * path )
{
return path [ 0 ] = = ' / ' ;
}
void
plat_path_slash ( char * path )
{
if ( ( path [ strlen ( path ) - 1 ] ! = ' / ' ) ) {
strcat ( path , " / " ) ;
}
}
void
plat_put_backslash ( char * s )
{
int c = strlen ( s ) - 1 ;
if ( s [ c ] ! = ' / ' )
s [ c ] = ' / ' ;
}
/* Return the last element of a pathname. */
char *
plat_get_basename ( const char * path )
{
int c = ( int ) strlen ( path ) ;
while ( c > 0 ) {
if ( path [ c ] = = ' / ' )
return ( ( char * ) & path [ c ] ) ;
c - - ;
}
return ( ( char * ) path ) ;
}
char *
plat_get_filename ( char * s )
{
int c = strlen ( s ) - 1 ;
while ( c > 0 ) {
if ( s [ c ] = = ' / ' | | s [ c ] = = ' \\ ' )
return ( & s [ c + 1 ] ) ;
c - - ;
}
return ( s ) ;
}
char *
plat_get_extension ( char * s )
{
int c = strlen ( s ) - 1 ;
if ( c < = 0 )
return ( s ) ;
while ( c & & s [ c ] ! = ' . ' )
c - - ;
if ( ! c )
return ( & s [ strlen ( s ) ] ) ;
return ( & s [ c + 1 ] ) ;
}
void
plat_append_filename ( char * dest , const char * s1 , const char * s2 )
{
strcpy ( dest , s1 ) ;
plat_path_slash ( dest ) ;
strcat ( dest , s2 ) ;
}
int
plat_dir_check ( char * path )
{
struct stat dummy ;
if ( stat ( path , & dummy ) < 0 )
{
return 0 ;
}
return S_ISDIR ( dummy . st_mode ) ;
}
int
plat_dir_create ( char * path )
{
return mkdir ( path , S_IRWXU ) ;
}
uint64_t
plat_timer_read ( void )
{
return SDL_GetPerformanceCounter ( ) ;
}
static uint64_t
plat_get_ticks_common ( void )
{
uint64_t EndingTime , ElapsedMicroseconds ;
if ( first_use ) {
Frequency = SDL_GetPerformanceFrequency ( ) ;
StartingTime = SDL_GetPerformanceCounter ( ) ;
first_use = 0 ;
}
EndingTime = SDL_GetPerformanceCounter ( ) ;
ElapsedMicroseconds = ( ( EndingTime - StartingTime ) * 1000000 ) / Frequency ;
return ElapsedMicroseconds ;
}
uint32_t
plat_get_ticks ( void )
{
return ( uint32_t ) ( plat_get_ticks_common ( ) / 1000 ) ;
}
uint32_t
plat_get_micro_ticks ( void )
{
return ( uint32_t ) plat_get_ticks_common ( ) ;
}
void plat_remove ( char * path )
{
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
ui_sb_update_panes ( )
{
}
void
plat_get_dirname ( char * dest , const char * path )
{
int c = ( int ) strlen ( path ) ;
char * ptr ;
ptr = ( char * ) path ;
while ( c > 0 ) {
if ( path [ c ] = = ' / ' | | path [ c ] = = ' \\ ' ) {
ptr = ( char * ) & path [ c ] ;
break ;
}
c - - ;
}
/* Copy to destination. */
while ( path < ptr )
* dest + + = * path + + ;
* dest = ' \0 ' ;
}
volatile int cpu_thread_run = 1 ;
void ui_sb_set_text_w ( wchar_t * wstr )
{
}
int stricmp ( const char * s1 , const char * s2 )
{
return strcasecmp ( s1 , s2 ) ;
}
int strnicmp ( const char * s1 , const char * s2 , size_t n )
{
return strncasecmp ( s1 , s2 , n ) ;
}
void
main_thread ( void * param )
{
uint32_t old_time , new_time ;
int drawits , frames ;
2021-08-28 23:06:07 +06:00
SDL_SetThreadPriority ( SDL_THREAD_PRIORITY_HIGH ) ;
2021-08-22 16:32:52 +06:00
framecountx = 0 ;
//title_update = 1;
old_time = SDL_GetTicks ( ) ;
drawits = frames = 0 ;
while ( ! is_quit & & cpu_thread_run ) {
/* See if it is time to run a frame of code. */
new_time = SDL_GetTicks ( ) ;
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 ( doresize & & ! video_fullscreen & & ! is_quit ) {
if ( vid_resize & 2 )
plat_resize ( fixed_size_x , fixed_size_y ) ;
else
plat_resize ( scrnsz_x , scrnsz_y ) ;
doresize = 0 ;
}
}
is_quit = 1 ;
}
thread_t * thMain = NULL ;
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 )
{
2021-08-29 15:41:06 +06:00
if ( SDL_ThreadID ( ) ! = eventthread )
{
exit_event = 1 ;
return ;
}
2021-08-23 17:26:04 +06:00
if ( blitreq )
{
blitreq = 0 ;
extern void video_blit_complete ( ) ;
video_blit_complete ( ) ;
}
2021-08-29 15:41:06 +06:00
while ( SDL_TryLockMutex ( blitmtx ) = = SDL_MUTEX_TIMEDOUT )
{
if ( blitreq )
{
blitreq = 0 ;
extern void video_blit_complete ( ) ;
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 ;
}
int ui_msgbox ( int flags , void * message )
{
2021-08-28 00:37:09 +06:00
return ui_msgbox_header ( flags , message , NULL ) ;
2021-08-22 16:32:52 +06:00
}
int ui_msgbox_header ( int flags , void * message , void * header )
{
2021-08-28 00:37:09 +06:00
if ( ! header ) header = L " 86Box " ;
2021-08-29 00:53:18 +06:00
if ( flags & MBX_ANSI )
2021-08-28 00:37:09 +06:00
{
2021-08-29 00:53:18 +06:00
fwprintf ( stderr , L " %s \n " , header ) ;
fprintf ( stderr , " ========================== \n "
" %s \n " , message ) ;
2021-08-28 00:37:09 +06:00
return 0 ;
}
2021-08-29 00:53:18 +06:00
fwprintf ( stderr , L " %s \n " , header ) ;
fwprintf ( stderr , L " ========================== \n "
L " %s \n " , plat_get_string ( message ) ) ;
2021-08-22 16:32:52 +06:00
return 0 ;
}
void plat_get_exe_name ( char * s , int size )
{
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 ;
}
2021-08-28 00:37:09 +06:00
void ui_sb_bugui ( char * str )
2021-08-22 16:32:52 +06:00
{
2021-08-28 00:37:09 +06:00
2021-08-22 16:32:52 +06:00
}
2021-08-23 15:56:24 +06:00
2021-08-22 16:32:52 +06:00
extern void sdl_blit ( int x , int y , int y1 , int y2 , int w , int h ) ;
2021-08-23 15:56:24 +06:00
typedef struct mouseinputdata
{
int deltax , deltay , deltaz ;
int mousebuttons ;
} mouseinputdata ;
SDL_mutex * mousemutex ;
static mouseinputdata mousedata ;
void mouse_poll ( )
{
SDL_LockMutex ( mousemutex ) ;
mouse_x = mousedata . deltax ;
mouse_y = mousedata . deltay ;
mouse_z = mousedata . deltaz ;
mousedata . deltax = mousedata . deltay = mousedata . deltaz = 0 ;
mouse_buttons = mousedata . mousebuttons ;
SDL_UnlockMutex ( mousemutex ) ;
}
extern int real_sdl_w , real_sdl_h ;
2021-08-22 16:32:52 +06:00
void ui_sb_set_ready ( int ready ) { }
2021-08-25 22:34:58 +06:00
char * xargv [ 512 ] ;
// From musl.
char * local_strsep ( char * * str , const char * sep )
{
char * s = * str , * end ;
if ( ! s ) return NULL ;
end = s + strcspn ( s , sep ) ;
if ( * end ) * end + + = 0 ;
else end = 0 ;
* str = end ;
return s ;
}
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 ] ;
wchar_t title [ 512 ] ;
dopause = p ;
if ( p ) {
wcsncpy ( oldtitle , ui_window_title ( NULL ) , sizeof_w ( oldtitle ) - 1 ) ;
wcscpy ( title , oldtitle ) ;
wcscat ( title , L " - PAUSED - " ) ;
ui_window_title ( title ) ;
} else {
ui_window_title ( oldtitle ) ;
}
}
2021-08-26 17:09:39 +06:00
2021-08-28 12:18:14 +06:00
bool process_media_commands_3 ( uint8_t * id , char * fn , uint8_t * wp , int cmdargc )
{
bool err = false ;
* id = atoi ( xargv [ 1 ] ) ;
if ( xargv [ 2 ] [ 0 ] = = ' \' ' | | xargv [ 2 ] [ 0 ] = = ' " ' )
{
int curarg = 2 ;
for ( curarg = 2 ; curarg < cmdargc ; curarg + + )
{
if ( strlen ( fn ) + strlen ( xargv [ curarg ] ) > = PATH_MAX )
{
err = true ;
fprintf ( stderr , " Path name too long. \n " ) ;
}
strcat ( fn , xargv [ curarg ] + ( xargv [ curarg ] [ 0 ] = = ' \' ' | | xargv [ curarg ] [ 0 ] = = ' " ' ) ) ;
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
| | fn [ strlen ( fn ) - 1 ] = = ' " ' )
{
if ( curarg + 1 < cmdargc )
{
* wp = atoi ( xargv [ curarg + 1 ] ) ;
}
break ;
}
strcat ( fn , " " ) ;
}
}
else
{
if ( strlen ( xargv [ 2 ] ) < PATH_MAX )
{
strcpy ( fn , xargv [ 2 ] ) ;
* wp = atoi ( xargv [ 3 ] ) ;
}
else
{
fprintf ( stderr , " Path name too long. \n " ) ;
err = true ;
}
}
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
| | fn [ strlen ( fn ) - 1 ] = = ' " ' ) fn [ strlen ( fn ) - 1 ] = ' \0 ' ;
return err ;
}
2021-08-28 13:56:23 +06: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__
# define LIBEDIT_LIBRARY "libedit.dylib"
# else
# define LIBEDIT_LIBRARY "libedit.so"
# endif
2021-08-29 00:53:18 +06:00
uint32_t timer_onesec ( uint32_t interval , void * param )
{
pc_onesec ( ) ;
return interval ;
}
2021-08-28 12:18:14 +06:00
2021-08-25 15:17:46 +06:00
void monitor_thread ( void * param )
{
2021-08-30 00:41:40 +06:00
# ifndef USE_CLI
2021-08-25 15:17:46 +06:00
if ( isatty ( fileno ( stdin ) ) & & isatty ( fileno ( stdout ) ) )
{
2021-08-25 15:34:40 +06:00
char * line = NULL ;
size_t n ;
2021-08-25 15:17:46 +06:00
printf ( " 86Box monitor console. \n " ) ;
2021-08-25 15:34:40 +06:00
while ( ! exit_event )
{
2021-08-25 22:34:58 +06:00
if ( feof ( stdin ) ) break ;
2021-08-28 13:56:23 +06:00
if ( f_readline )
line = f_readline ( " (86Box) " ) ;
else
{
printf ( " (86Box) " ) ;
getline ( & line , & n , stdin ) ;
}
2021-08-25 15:34:40 +06:00
if ( line )
{
2021-08-25 22:34:58 +06:00
int cmdargc = 0 ;
char * linecpy ;
line [ strcspn ( line , " \r \n " ) ] = ' \0 ' ;
linecpy = strdup ( line ) ;
if ( ! linecpy )
{
free ( line ) ;
line = NULL ;
continue ;
}
2021-08-28 13:56:23 +06:00
if ( f_add_history ) f_add_history ( line ) ;
2021-08-25 22:34:58 +06:00
memset ( xargv , 0 , sizeof ( xargv ) ) ;
while ( 1 )
{
xargv [ cmdargc + + ] = local_strsep ( & linecpy , " " ) ;
if ( xargv [ cmdargc - 1 ] = = NULL | | cmdargc > = 512 ) break ;
}
if ( strncasecmp ( xargv [ 0 ] , " exit " , 4 ) = = 0 )
2021-08-25 15:34:40 +06:00
{
exit_event = 1 ;
2021-08-25 15:47:24 +06:00
}
2021-09-04 00:28:41 +06:00
else if ( strncasecmp ( xargv [ 0 ] , " fullscreen " , 10 ) = = 0 )
2021-08-29 15:41:06 +06:00
{
video_fullscreen = 1 ;
fullscreen_pending = 1 ;
}
2021-08-28 00:45:35 +06:00
else if ( strncasecmp ( xargv [ 0 ] , " pause " , 5 ) = = 0 )
{
plat_pause ( dopause ^ 1 ) ;
2021-08-28 12:18:14 +06:00
printf ( " %s " , dopause ? " Paused. \n " : " Unpaused. \n " ) ;
2021-08-28 00:45:35 +06:00
}
2021-08-26 17:09:39 +06:00
else if ( strncasecmp ( xargv [ 0 ] , " hardreset " , 9 ) = = 0 )
{
pc_reset_hard ( ) ;
}
else if ( strncasecmp ( xargv [ 0 ] , " cdload " , 6 ) = = 0 & & cmdargc > = 3 )
{
uint8_t id ;
bool err = false ;
char fn [ PATH_MAX ] ;
2021-08-28 12:18:14 +06:00
2021-08-26 17:41:55 +06:00
if ( ! xargv [ 2 ] | | ! xargv [ 1 ] )
{
free ( line ) ;
free ( linecpy ) ;
line = NULL ;
continue ;
}
2021-08-26 17:09:39 +06:00
id = atoi ( xargv [ 1 ] ) ;
memset ( fn , 0 , sizeof ( fn ) ) ;
if ( xargv [ 2 ] [ 0 ] = = ' \' ' | | xargv [ 2 ] [ 0 ] = = ' " ' )
{
int curarg = 2 ;
for ( curarg = 2 ; curarg < cmdargc ; curarg + + )
{
if ( strlen ( fn ) + strlen ( xargv [ curarg ] ) > = PATH_MAX )
{
err = true ;
fprintf ( stderr , " Path name too long. \n " ) ;
}
strcat ( fn , xargv [ curarg ] + ( xargv [ curarg ] [ 0 ] = = ' \' ' | | xargv [ curarg ] [ 0 ] = = ' " ' ) ) ;
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
| | fn [ strlen ( fn ) - 1 ] = = ' " ' )
{
break ;
}
strcat ( fn , " " ) ;
}
}
else
{
if ( strlen ( xargv [ 2 ] ) < PATH_MAX )
{
strcpy ( fn , xargv [ 2 ] ) ;
}
else
{
fprintf ( stderr , " Path name too long. \n " ) ;
}
}
if ( ! err )
{
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
| | 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 ) ;
}
}
2021-08-28 23:06:07 +06:00
else if ( strncasecmp ( xargv [ 0 ] , " fddeject " , 8 ) = = 0 & & cmdargc > = 2 )
2021-08-27 01:11:52 +06:00
{
2021-08-28 23:06:07 +06:00
floppy_eject ( atoi ( xargv [ 1 ] ) ) ;
2021-08-27 01:11:52 +06:00
}
2021-08-28 23:06:07 +06:00
else if ( strncasecmp ( xargv [ 0 ] , " cdeject " , 8 ) = = 0 & & cmdargc > = 2 )
2021-08-27 01:11:52 +06:00
{
2021-08-28 23:06:07 +06:00
cdrom_mount ( atoi ( xargv [ 1 ] ) , " " ) ;
2021-08-28 12:18:14 +06:00
}
2021-08-28 23:06:07 +06:00
else if ( strncasecmp ( xargv [ 0 ] , " moeject " , 8 ) = = 0 & & cmdargc > = 2 )
2021-08-28 12:18:14 +06:00
{
2021-08-28 23:06:07 +06:00
mo_eject ( atoi ( xargv [ 1 ] ) ) ;
2021-08-28 12:18:14 +06:00
}
2021-08-28 23:06:07 +06:00
else if ( strncasecmp ( xargv [ 0 ] , " carteject " , 8 ) = = 0 & & cmdargc > = 2 )
2021-08-28 12:18:14 +06:00
{
2021-08-28 23:06:07 +06:00
cartridge_eject ( atoi ( xargv [ 1 ] ) ) ;
2021-08-28 12:18:14 +06:00
}
2021-08-28 23:06:07 +06:00
else if ( strncasecmp ( xargv [ 0 ] , " zipeject " , 8 ) = = 0 & & cmdargc > = 2 )
2021-08-28 12:18:14 +06:00
{
2021-08-28 23:06:07 +06:00
zip_eject ( atoi ( xargv [ 1 ] ) ) ;
2021-08-27 01:11:52 +06:00
}
2021-08-25 22:34:58 +06:00
else if ( strncasecmp ( xargv [ 0 ] , " fddload " , 7 ) = = 0 & & cmdargc > = 4 )
2021-08-25 15:47:24 +06:00
{
2021-08-25 22:34:58 +06:00
uint8_t id , wp ;
bool err = false ;
char fn [ PATH_MAX ] ;
memset ( fn , 0 , sizeof ( fn ) ) ;
2021-08-26 17:41:55 +06:00
if ( ! xargv [ 2 ] | | ! xargv [ 1 ] )
{
free ( line ) ;
free ( linecpy ) ;
line = NULL ;
continue ;
}
2021-08-28 12:18:14 +06:00
err = process_media_commands_3 ( & id , fn , & wp , cmdargc ) ;
if ( ! err )
2021-08-25 22:34:58 +06:00
{
2021-08-28 12:18:14 +06:00
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
| | fn [ strlen ( fn ) - 1 ] = = ' " ' ) fn [ strlen ( fn ) - 1 ] = ' \0 ' ;
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
}
2021-08-28 12:18:14 +06:00
}
else if ( strncasecmp ( xargv [ 0 ] , " moload " , 7 ) = = 0 & & cmdargc > = 4 )
{
uint8_t id , wp ;
bool err = false ;
char fn [ PATH_MAX ] ;
memset ( fn , 0 , sizeof ( fn ) ) ;
if ( ! xargv [ 2 ] | | ! xargv [ 1 ] )
2021-08-25 22:34:58 +06:00
{
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 ) ;
2021-08-25 22:34:58 +06:00
if ( ! err )
{
2021-08-26 17:09:39 +06:00
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
| | 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 ) ;
}
}
else if ( strncasecmp ( xargv [ 0 ] , " cartload " , 7 ) = = 0 & & cmdargc > = 4 )
{
uint8_t id , wp ;
bool err = false ;
char fn [ PATH_MAX ] ;
memset ( fn , 0 , sizeof ( fn ) ) ;
if ( ! xargv [ 2 ] | | ! xargv [ 1 ] )
{
free ( line ) ;
free ( linecpy ) ;
line = NULL ;
continue ;
}
err = process_media_commands_3 ( & id , fn , & wp , cmdargc ) ;
if ( ! err )
{
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
| | fn [ strlen ( fn ) - 1 ] = = ' " ' ) fn [ strlen ( fn ) - 1 ] = ' \0 ' ;
printf ( " Inserting tape into cartridge holder %hhu: %s \n " , id , fn ) ;
cartridge_mount ( id , fn , wp ) ;
}
}
else if ( strncasecmp ( xargv [ 0 ] , " zipload " , 7 ) = = 0 & & cmdargc > = 4 )
{
uint8_t id , wp ;
bool err = false ;
char fn [ PATH_MAX ] ;
memset ( fn , 0 , sizeof ( fn ) ) ;
if ( ! xargv [ 2 ] | | ! xargv [ 1 ] )
{
free ( line ) ;
free ( linecpy ) ;
line = NULL ;
continue ;
}
err = process_media_commands_3 ( & id , fn , & wp , cmdargc ) ;
if ( ! err )
{
if ( fn [ strlen ( fn ) - 1 ] = = ' \' '
| | fn [ strlen ( fn ) - 1 ] = = ' " ' ) fn [ strlen ( fn ) - 1 ] = ' \0 ' ;
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
2021-08-22 16:32:52 +06:00
int main ( int argc , char * * argv )
{
SDL_Event event ;
2021-08-28 23:06:07 +06:00
void * libedithandle ;
2021-08-22 16:32:52 +06:00
SDL_Init ( 0 ) ;
pc_init ( argc , argv ) ;
if ( ! pc_init_modules ( ) ) {
fprintf ( stderr , " No ROMs found. \n " ) ;
SDL_Quit ( ) ;
return 6 ;
}
2021-08-26 00:15:42 +06:00
eventthread = SDL_ThreadID ( ) ;
2021-08-22 16:32:52 +06:00
blitmtx = SDL_CreateMutex ( ) ;
if ( ! blitmtx )
{
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 ) ;
if ( libedithandle )
{
f_readline = dlsym ( libedithandle , " readline " ) ;
f_add_history = dlsym ( libedithandle , " add_history " ) ;
if ( ! f_readline )
{
fprintf ( stderr , " readline in libedit not found, line editing will be limited. \n " ) ;
}
f_rl_callback_handler_remove = dlsym ( libedithandle , " rl_callback_handler_remove " ) ;
}
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 ( ) ;
if ( start_in_fullscreen )
2021-08-29 15:41:06 +06:00
{
video_fullscreen = 1 ;
sdl_set_fs ( 1 ) ;
}
2021-08-22 16:32:52 +06:00
/* Fire up the machine. */
pc_reset_hard_init ( ) ;
/* Set the PAUSE mode depending on the renderer. */
//plat_pause(0);
/* 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 ) ;
2021-08-22 16:32:52 +06:00
while ( ! is_quit )
{
2021-08-29 00:34:03 +06:00
while ( SDL_PollEvent ( & event ) )
{
switch ( event . type )
2021-08-23 15:56:24 +06:00
{
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
{
2021-08-29 00:34:03 +06:00
if ( mouse_capture | | video_fullscreen )
2021-08-23 15:56:24 +06:00
{
2021-08-29 00:34:03 +06:00
if ( event . wheel . direction = = SDL_MOUSEWHEEL_FLIPPED )
{
event . wheel . x * = - 1 ;
event . wheel . y * = - 1 ;
}
SDL_LockMutex ( mousemutex ) ;
mousedata . deltaz = event . wheel . y ;
SDL_UnlockMutex ( mousemutex ) ;
2021-08-23 15:56:24 +06:00
}
break ;
}
2021-08-29 00:34:03 +06:00
case SDL_MOUSEMOTION :
2021-08-23 15:56:24 +06:00
{
2021-08-29 00:34:03 +06:00
if ( mouse_capture | | video_fullscreen )
{
SDL_LockMutex ( mousemutex ) ;
mousedata . deltax + = event . motion . xrel ;
mousedata . deltay + = event . motion . yrel ;
SDL_UnlockMutex ( mousemutex ) ;
}
2021-08-23 15:56:24 +06:00
break ;
}
2021-08-29 00:34:03 +06:00
case SDL_MOUSEBUTTONDOWN :
case SDL_MOUSEBUTTONUP :
2021-08-23 15:56:24 +06:00
{
2021-08-29 00:34:03 +06:00
if ( ( event . button . button = = SDL_BUTTON_LEFT )
& & ! ( mouse_capture | | video_fullscreen )
& & event . button . state = = SDL_RELEASED
& & event . button . x < = real_sdl_w & & event . button . y < = real_sdl_h )
2021-08-23 15:56:24 +06:00
{
2021-08-29 00:34:03 +06:00
plat_mouse_capture ( 1 ) ;
break ;
2021-08-23 15:56:24 +06:00
}
2021-08-29 00:34:03 +06:00
if ( mouse_get_buttons ( ) < 3 & & event . button . button = = SDL_BUTTON_MIDDLE & & ! video_fullscreen )
2021-08-23 15:56:24 +06:00
{
2021-08-29 00:34:03 +06:00
plat_mouse_capture ( 0 ) ;
break ;
}
if ( mouse_capture | | video_fullscreen )
{
int buttonmask = 0 ;
switch ( event . button . button )
{
case SDL_BUTTON_LEFT :
buttonmask = 1 ;
break ;
case SDL_BUTTON_RIGHT :
buttonmask = 2 ;
break ;
case SDL_BUTTON_MIDDLE :
buttonmask = 4 ;
break ;
}
SDL_LockMutex ( mousemutex ) ;
if ( event . button . state = = SDL_PRESSED )
{
mousedata . mousebuttons | = buttonmask ;
}
else mousedata . mousebuttons & = ~ buttonmask ;
SDL_UnlockMutex ( mousemutex ) ;
2021-08-23 15:56:24 +06:00
}
2021-08-25 00:09:02 +06:00
break ;
}
2021-08-29 00:34:03 +06:00
case SDL_RENDER_DEVICE_RESET :
case SDL_RENDER_TARGETS_RESET :
{
extern void sdl_reinit_texture ( ) ;
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 :
{
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-23 00:47:07 +06:00
}
}
2021-08-29 00:34:03 +06:00
}
2021-08-23 15:56:24 +06:00
if ( mouse_capture & & keyboard_ismsexit ( ) )
{
plat_mouse_capture ( 0 ) ;
2021-08-26 00:15:42 +06:00
}
2021-08-22 16:32:52 +06:00
if ( blitreq )
{
extern void sdl_blit ( int x , int y , int y1 , int y2 , int w , int h ) ;
sdl_blit ( params . x , params . y , params . y1 , params . y2 , params . w , params . h ) ;
}
2021-08-26 00:15:42 +06:00
if ( title_set )
2021-08-23 14:09:43 +06:00
{
2021-08-26 00:15:42 +06:00
extern void ui_window_title_real ( ) ;
ui_window_title_real ( ) ;
2021-08-23 14:09:43 +06:00
}
2021-08-29 15:41:06 +06:00
if ( video_fullscreen & & keyboard_isfsexit ( ) )
{
sdl_set_fs ( 0 ) ;
video_fullscreen = 0 ;
}
if ( fullscreen_pending )
{
sdl_set_fs ( video_fullscreen ) ;
fullscreen_pending = 0 ;
}
2021-08-25 00:09:02 +06:00
if ( exit_event )
{
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 ( ) ;
2021-08-28 14:59:12 +06:00
if ( f_rl_callback_handler_remove ) f_rl_callback_handler_remove ( ) ;
2021-08-22 16:32:52 +06:00
return 0 ;
}
char * plat_vidapi_name ( int i )
{
return " default " ;
}
void joystick_init ( void ) { }
void joystick_close ( void ) { }
void joystick_process ( void ) { }
void startblit ( )
{
SDL_LockMutex ( blitmtx ) ;
}
void endblit ( )
{
SDL_UnlockMutex ( blitmtx ) ;
2021-08-25 02:01:39 +06:00
}