Files
86Box/src/unix/unix.c

1432 lines
41 KiB
C
Raw Normal View History

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
#include <SDL.h>
2021-08-22 16:32:52 +06:00
#include <stdlib.h>
#include <stdbool.h>
2021-08-22 16:32:52 +06:00
#include <stdio.h>
#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>
#include <wchar.h>
2022-04-08 15:00:35 +06:00
#include <pwd.h>
#include <stdatomic.h>
2023-08-30 12:43:34 -04:00
#ifdef __APPLE__
# include "macOSXGlue.h"
#endif
2021-08-22 16:32:52 +06:00
#include <86box/86box.h>
#include <86box/mem.h>
#include <86box/rom.h>
#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-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;
int status_icons_fullscreen = 0; /* unused. */
2022-09-18 17:17:34 -04:00
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,
[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,
[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,
[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,
[SDL_SCANCODE_APPLICATION] = 0x15D,
[SDL_SCANCODE_PRINTSCREEN] = 0x137
};
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);
2023-08-30 12:43:53 -04:00
2022-09-18 17:17:34 -04:00
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;
}
}
}
2023-08-30 12:43:53 -04:00
2021-08-22 16:32:52 +06:00
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:
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:
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";
case IDS_2095:
2021-08-28 00:37:09 +06:00
return L"No PCap devices found";
2022-11-08 04:18:33 -05:00
case IDS_2096:
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";
case IDS_2133:
2021-08-28 00:37:09 +06:00
return L"libgs is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files.";
2022-11-08 04:18:33 -05:00
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";
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:
return L"Hardware not available";
2022-11-08 04:18:33 -05:00
case IDS_2143:
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] == '/';
}
void
2022-09-18 17:17:34 -04:00
path_normalize(char *path)
2021-08-22 16:32:52 +06:00
{
/* No-op. */
}
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 *
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);
}
void *
plat_mmap(size_t size, uint8_t executable)
{
2021-10-19 23:44:47 +06:00
#if defined __APPLE__ && defined MAP_JIT
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
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
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;
2023-08-30 12:43:53 -04:00
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;
2023-08-30 12:43:53 -04:00
2021-08-22 16:32:52 +06:00
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)
{
2023-08-30 12:43:53 -04:00
/* No-op. */
2021-08-22 16:32:52 +06:00
}
void
ui_sb_update_icon(int tag, int active)
{
2023-08-30 12:43:53 -04:00
/* No-op. */
2021-08-22 16:32:52 +06:00
}
void
plat_delay_ms(uint32_t count)
{
SDL_Delay(count);
}
void
ui_sb_update_tip(int arg)
{
2023-08-30 12:43:53 -04:00
/* No-op. */
2021-08-22 16:32:52 +06:00
}
void
2022-12-19 19:45:39 -05:00
ui_sb_update_panes(void)
2021-08-22 16:32:52 +06:00
{
2023-08-30 12:43:53 -04:00
/* No-op. */
2021-08-22 16:32:52 +06:00
}
void
2022-12-19 19:45:39 -05:00
ui_sb_update_text(void)
{
2023-08-30 12:43:53 -04:00
/* No-op. */
}
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);
2023-08-30 12:43:53 -04:00
char *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
{
2023-08-30 12:43:53 -04:00
/* No-op. */
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
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) {
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-29 15:41:06 +06:00
is_quit = 1;
2021-08-22 16:32:52 +06:00
sdl_close();
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;
2023-08-30 12:43:53 -04:00
2022-09-18 17:17:34 -04:00
if (!header)
header = (void *) ((flags & MBX_ANSI) ? "86Box" : L"86Box");
2022-09-18 17:17:34 -04:00
if (header <= (void *) 7168)
2023-08-30 14:00:49 -04:00
header = (void *) plat_get_string((uintptr_t) header);
2022-09-18 17:17:34 -04:00
if (message <= (void *) 7168)
2023-08-30 14:00:49 -04:00
message = (void *) plat_get_string((uintptr_t) 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();
2023-08-30 12:43:53 -04:00
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
{
2023-08-30 12:43:53 -04:00
/* No-op. */
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;
2023-08-30 12:43:53 -04:00
SDL_mutex *mousemutex;
int real_sdl_w;
int real_sdl_h;
2022-09-18 17:17:34 -04:00
void
ui_sb_set_ready(int ready)
2021-08-23 15:56:24 +06:00
{
2023-08-30 12:43:53 -04:00
/* No-op. */
2021-08-23 15:56:24 +06:00
}
2022-09-18 17:17:34 -04:00
char *xargv[512];
// From musl.
2022-09-18 17:17:34 -04:00
char *
local_strsep(char **str, const char *sep)
{
2023-05-29 01:30:51 -04:00
char *s = *str;
char *end;
2023-08-30 12:43:53 -04:00
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;
2023-08-30 12:43:53 -04:00
2022-09-18 17:17:34 -04:00
return s;
}
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
2023-12-27 21:30:47 +01:00
if ((!!p) == dopause)
return;
if ((p == 0) && (time_sync & TIME_SYNC_ENABLED))
2022-09-18 17:17:34 -04:00
nvr_time_sync();
2023-12-27 21:30:47 +01:00
do_pause(p);
2021-08-28 00:45:35 +06:00
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
}
}
void
2022-12-19 19:45:39 -05:00
plat_init_rom_paths(void)
{
#ifndef __APPLE__
if (getenv("XDG_DATA_HOME")) {
char xdg_rom_path[1024] = { 0 };
2023-08-30 12:43:53 -04:00
strncpy(xdg_rom_path, getenv("XDG_DATA_HOME"), 1024);
2022-04-19 23:06:39 +02:00
path_slash(xdg_rom_path);
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);
rom_add_path(xdg_rom_path);
} else {
char home_rom_path[1024] = { 0 };
2023-08-30 12:43:53 -04:00
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);
rom_add_path(home_rom_path);
}
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;
2023-08-30 12:43:53 -04: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);
strcat(real_xdg_rom_path, "86Box/roms/");
rom_add_path(real_xdg_rom_path);
}
}
free(xdg_rom_paths_orig);
} else {
rom_add_path("/usr/local/share/86Box/roms/");
rom_add_path("/usr/share/86Box/roms/");
}
#else
char default_rom_path[1024] = { '\0' };
getDefaultROMPath(default_rom_path);
2022-05-21 11:23:14 +02:00
rom_add_path(default_rom_path);
#endif
}
2022-11-06 22:32:58 +06:00
void
plat_get_global_config_dir(char *strptr)
{
#ifdef __APPLE__
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)
{
bool err = false;
2023-08-30 12:43:53 -04:00
2022-09-18 17:17:34 -04:00
*id = atoi(xargv[1]);
2023-08-30 12:43:53 -04:00
2022-09-18 17:17:34 -04:00
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) {
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) {
*wp = atoi(xargv[curarg + 1]);
}
break;
}
strcat(fn, " ");
}
2022-09-18 17:17:34 -04:00
} else {
if (strlen(xargv[2]) < PATH_MAX) {
strcpy(fn, xargv[2]);
*wp = atoi(xargv[3]);
2022-09-18 17:17:34 -04:00
} else {
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';
return err;
}
2022-09-18 17:17:34 -04:00
char *(*f_readline)(const char *) = NULL;
int (*f_add_history)(const char *) = NULL;
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
2023-08-30 12:43:53 -04:00
2022-09-18 17:17:34 -04:00
uint32_t
timer_onesec(uint32_t interval, void *param)
{
2022-09-18 17:17:34 -04:00
pc_onesec();
return interval;
}
2022-09-18 17:17:34 -04:00
void
monitor_thread(void *param)
{
#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;
2023-08-30 12:43:53 -04:00
printf("86Box monitor console.\n");
2022-09-18 17:17:34 -04:00
while (!exit_event) {
if (feof(stdin))
break;
#ifdef ENABLE_READLINE
2021-08-28 13:56:23 +06:00
if (f_readline)
line = f_readline("(86Box) ");
2022-09-18 17:17:34 -04:00
else {
#endif
2021-08-28 13:56:23 +06:00
printf("(86Box) ");
(void) !getline(&line, &n, stdin);
#ifdef ENABLE_READLINE
2021-08-28 13:56:23 +06:00
}
#endif
2022-09-18 17:17:34 -04:00
if (line) {
int cmdargc = 0;
char *linecpy;
2023-08-30 12:43:53 -04:00
line[strcspn(line, "\r\n")] = '\0';
2022-09-18 17:17:34 -04:00
linecpy = strdup(line);
if (!linecpy) {
free(line);
line = NULL;
continue;
}
2022-09-18 17:17:34 -04:00
if (f_add_history)
f_add_history(line);
memset(xargv, 0, sizeof(xargv));
2022-09-18 17:17:34 -04:00
while (1) {
xargv[cmdargc++] = local_strsep(&linecpy, " ");
2022-09-18 17:17:34 -04:00
if (xargv[cmdargc - 1] == NULL || cmdargc >= 512)
break;
}
cmdargc--;
2022-09-18 17:17:34 -04:00
if (strncasecmp(xargv[0], "help", 4) == 0) {
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"
"version - print version and license information.\n"
"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;
} 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"
"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);
printf("%s", dopause ? "Paused.\n" : "Unpaused.\n");
2022-09-18 17:17:34 -04:00
} else if (strncasecmp(xargv[0], "hardreset", 9) == 0) {
pc_reset_hard();
2022-09-18 17:17:34 -04:00
} else if (strncasecmp(xargv[0], "cdload", 6) == 0 && cmdargc >= 3) {
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;
}
id = atoi(xargv[1]);
memset(fn, 0, sizeof(fn));
2022-09-18 17:17:34 -04:00
if (xargv[2][0] == '\'' || xargv[2][0] == '"') {
int curarg = 2;
2023-08-30 12:43:53 -04:00
2022-09-18 17:17:34 -04:00
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] == '\''
2022-09-18 17:17:34 -04:00
|| fn[strlen(fn) - 1] == '"') {
break;
}
strcat(fn, " ");
}
2022-09-18 17:17:34 -04:00
} else {
if (strlen(xargv[2]) < PATH_MAX) {
strcpy(fn, xargv[2]);
2022-09-18 17:17:34 -04:00
} else {
fprintf(stderr, "Path name too long.\n");
}
}
2022-09-18 17:17:34 -04:00
if (!err) {
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);
cdrom_mount(id, fn);
}
2022-09-18 17:17:34 -04:00
} else if (strncasecmp(xargv[0], "fddeject", 8) == 0 && cmdargc >= 2) {
floppy_eject(atoi(xargv[1]));
2022-09-18 17:17:34 -04:00
} else if (strncasecmp(xargv[0], "cdeject", 8) == 0 && cmdargc >= 2) {
cdrom_mount(atoi(xargv[1]), "");
2022-09-18 17:17:34 -04:00
} else if (strncasecmp(xargv[0], "moeject", 8) == 0 && cmdargc >= 2) {
mo_eject(atoi(xargv[1]));
2022-09-18 17:17:34 -04:00
} else if (strncasecmp(xargv[0], "carteject", 8) == 0 && cmdargc >= 2) {
cartridge_eject(atoi(xargv[1]));
2022-09-18 17:17:34 -04:00
} else if (strncasecmp(xargv[0], "zipeject", 8) == 0 && cmdargc >= 2) {
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];
2023-08-30 12:43:53 -04:00
memset(fn, 0, sizeof(fn));
2023-08-30 12:43:53 -04: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;
}
err = process_media_commands_3(&id, fn, &wp, cmdargc);
2022-09-18 17:17:34 -04:00
if (!err) {
if (fn[strlen(fn) - 1] == '\''
2022-09-18 17:17:34 -04:00
|| 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);
}
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];
2023-08-30 12:43:53 -04:00
memset(fn, 0, sizeof(fn));
2023-08-30 12:43:53 -04:00
2022-09-18 17:17:34 -04:00
if (!xargv[2] || !xargv[1]) {
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) {
if (fn[strlen(fn) - 1] == '\''
2022-09-18 17:17:34 -04:00
|| fn[strlen(fn) - 1] == '"')
fn[strlen(fn) - 1] = '\0';
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];
2023-08-30 12:43:53 -04:00
memset(fn, 0, sizeof(fn));
2023-08-30 12:43:53 -04:00
2022-09-18 17:17:34 -04:00
if (!xargv[2] || !xargv[1]) {
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) {
if (fn[strlen(fn) - 1] == '\''
2022-09-18 17:17:34 -04:00
|| 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);
}
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];
2023-08-30 12:43:53 -04:00
memset(fn, 0, sizeof(fn));
2023-08-30 12:43:53 -04:00
2022-09-18 17:17:34 -04:00
if (!xargv[2] || !xargv[1]) {
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) {
if (fn[strlen(fn) - 1] == '\''
2022-09-18 17:17:34 -04:00
|| 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 15:34:40 +06:00
}
free(line);
free(linecpy);
line = NULL;
2021-08-25 15:34:40 +06:00
}
}
}
#endif
}
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;
int ret = 0;
2021-08-22 16:32:52 +06:00
SDL_Init(0);
ret = pc_init(argc, argv);
if (ret == 0)
return 0;
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\nPlease 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;
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;
}
libedithandle = dlopen(LIBEDIT_LIBRARY, RTLD_LOCAL | RTLD_LAZY);
2022-09-18 17:17:34 -04:00
if (libedithandle) {
f_readline = dlsym(libedithandle, "readline");
f_add_history = dlsym(libedithandle, "add_history");
2022-09-18 17:17:34 -04:00
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");
2022-09-18 17:17:34 -04:00
} else
fprintf(stderr, "libedit not found, line editing will be limited.\n");
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. */
plat_pause(0);
2021-08-22 16:32:52 +06:00
/* Initialize the rendering window, or fullscreen. */
do_start();
#ifndef USE_CLI
2021-08-25 15:34:40 +06:00
thread_create(monitor_thread, NULL);
#endif
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;
2023-08-30 12:43:53 -04:00
2022-09-18 17:17:34 -04:00
while (SDL_PollEvent(&event)) {
switch (event.type) {
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);
mouse_set_z(event.wheel.y);
2022-09-18 17:17:34 -04:00
SDL_UnlockMutex(mousemutex);
}
2022-09-18 17:17:34 -04:00
break;
2021-08-23 15:56:24 +06:00
}
case SDL_MOUSEMOTION:
{
2022-09-18 17:17:34 -04:00
if (mouse_capture || video_fullscreen) {
SDL_LockMutex(mousemutex);
mouse_scale(event.motion.xrel, event.motion.yrel);
2022-09-18 17:17:34 -04:00
SDL_UnlockMutex(mousemutex);
}
break;
}
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;
}
2022-09-18 17:17:34 -04:00
if (mouse_get_buttons() < 3 && event.button.button == SDL_BUTTON_MIDDLE && !video_fullscreen) {
plat_mouse_capture(0);
break;
}
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);
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);
}
2022-09-18 17:17:34 -04:00
break;
2021-08-23 15:56:24 +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);
2023-08-30 12:43:53 -04:00
sdl_reinit_texture();
break;
}
case SDL_KEYDOWN:
case SDL_KEYUP:
{
2022-09-18 17:17:34 -04:00
uint16_t xtkey = 0;
2023-08-30 12:43:53 -04:00
2022-09-18 17:17:34 -04:00
switch (event.key.keysym.scancode) {
default:
xtkey = sdl_to_xt[event.key.keysym.scancode];
break;
}
keyboard_input(event.key.state == SDL_PRESSED, xtkey);
}
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
}
}
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) {
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);
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
}
printf("\n");
2021-08-22 16:32:52 +06:00
SDL_DestroyMutex(blitmtx);
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";
}
void
set_language(uint32_t id)
{
lang_id = id;
}
/* Sets up the program language before initialization. */
2022-09-18 17:17:34 -04:00
uint32_t
plat_language_code(char *langcode)
{
2022-02-20 02:26:27 -05:00
/* or maybe not */
return 0;
}
void
plat_get_cpu_string(char *outbuf, uint8_t len) {
char cpu_string[] = "Unknown";
2023-08-30 12:43:53 -04:00
strncpy(outbuf, cpu_string, len);
}
/* 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)
{
2022-02-20 02:26:27 -05:00
/* or maybe not */
return;
}
2022-09-18 17:17:34 -04:00
void
joystick_init(void)
{
2023-08-30 12:43:53 -04:00
/* No-op. */
2022-09-18 17:17:34 -04:00
}
2023-08-30 12:43:53 -04:00
2022-09-18 17:17:34 -04:00
void
joystick_close(void)
{
2023-08-30 12:43:53 -04:00
/* No-op. */
2022-09-18 17:17:34 -04:00
}
2023-08-30 12:43:53 -04:00
2022-09-18 17:17:34 -04:00
void
joystick_process(void)
{
2023-08-30 12:43:53 -04:00
/* No-op. */
2022-09-18 17:17:34 -04:00
}
2023-08-30 12:43:53 -04:00
2022-09-18 17:17:34 -04:00
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
{
2023-08-30 12:43:53 -04:00
/* No-op. */
}
2023-01-03 15:42:57 +06:00
void
ui_hard_reset_completed(void)
2022-02-07 22:58:08 +01:00
{
2023-08-30 12:43:53 -04:00
/* No-op. */
}