Merge branch '86Box:master' into PB68x-update

This commit is contained in:
Verloren50000
2025-10-28 09:39:15 +08:00
committed by GitHub
13 changed files with 5321 additions and 397 deletions

View File

@@ -0,0 +1,78 @@
UNIX MODE WITH OSD
86Box supports running on the linux framebuffer without QT and without X, making the pc appear as a nearly native old machine.
running it that way is already supported but when doing it, 86box loses all menu and all abilities to mount floppies and CDs, it also becomes the owner of the entire pc with no way of quitting it or changing virtual console.
to overcome this, an on screen display menu is available that allows doing everything the textual console (src/unix/unix.c) does;
mount/unmount all supported media like floppy and cd
hard reset the machine
quit 86box
seeing the current performance %
key bindings:
Right Control + F11 opens the osd
while is open:
arrows up, down moves the cursor
enter does the action, at mount options it enters a list of appropriate files (*.img, *.iso)
ESC goes back to main or closes the OSD
current limitations:
OSD can mount images to first floppy and first cd, secondary devices are not supported
it does not show if an image is mounted or not
the option "version" does actully print it, but it can't be seen beacuse its printed under 86box display
extremely long filenames can overflow the blue window
the title does actually overflow the window width :)
These are the steps to install a machine fully dedicated to 86Box and tuned to make it appear almost native.
This works almost the same for on a Raspberry Pi
1) install a vanilla Debian Trixie with netinst and without any graphical environment, or a "server" distro for RPI
depending on the machine speed, this will make boot time extremely short
2) apt update if necessary
3) install git and almost all required packages
apt install git build-essential cmake extra-cmake-modules pkg-config ninja-build libfreetype-dev libsdl2-dev libpng-dev libopenal-dev librtmidi-dev libfluidsynth-dev libsndfile1-dev libserialport-dev libevdev-dev libxkbcommon-dev libxkbcommon-x11-dev libslirp-dev
4) setup git and clone
git@github.com:86Box/86Box.git
git@github.com:86Box/roms.git
5) build (128 => super speed, too much for a 2GB machine)
cd 86Box
mkdir build
cd build
cmake .. --preset regular -D QT=OFF -D PREFER_STATIC=ON
cmake --build regular -j 128
cd ../../
ln -s 86Box/build/regular/src/86Box 86Box.exe
6) boot
as root so it can take complete ownership of the linux framebuffer
7) notes:
- 86Box will complain to be unable to find readline, this is fine, we don't need the command line at all
- ALSOFT will complain it can't connect to PipeWire, no problem, sounds will come from standard ALSA
8) additional steps
add a new udev rule to automount any USB key to a known location so files in it can be listed in the OSD floppy/cd mount options
create /etc/udev/rules.d/99-automount.rules
with:
ACTION=="add", ENV{ID_BUS}=="usb", ENV{ID_TYPE}=="disk", ENV{ID_FS_TYPE}=="exfat", RUN+="/usr/bin/systemd-mount --no-block --automount=yes --collect /dev/%k '/mnt'"
replicate this line for each filesystem you expect the usb key to be formatted, in this example "exfat"
this is going to conflict if multiple keys are inserted, don't do it
final step
configure some 86box vm using another pc with the GUI
copy the VM definitions to this new pc and manually launch 86box from the textual command line
optionally craft a boot menu to be shown in place of the login prompt or setup 86box as a debiasn service, it will start at boot
just make sure the pc will be accessible via ssh or some other way, autobooting 86box canà make difficult terminating it

View File

@@ -1083,7 +1083,10 @@ usage:
/* Build the global configuration file path. */
if (global == NULL) {
plat_get_global_config_dir(global_cfg_path, sizeof(global_cfg_path));
path_append_filename(global_cfg_path, global_cfg_path, GLOBAL_CONFIG_FILE);
// avoid strcpy global_cfg_path over itself (valgrind says it's bad...)
// path_append_filename(global_cfg_path, global_cfg_path, GLOBAL_CONFIG_FILE);
path_slash(global_cfg_path);
strcat(global_cfg_path, GLOBAL_CONFIG_FILE);
} else {
strncpy(global_cfg_path, global, sizeof(global_cfg_path) - 1);
}

View File

@@ -0,0 +1,25 @@
#ifndef _UNIX_OSD_H
#define _UNIX_OSD_H
#include <SDL.h>
// state management
extern void osd_init(void);
extern void osd_deinit(void);
extern int osd_open(SDL_Event event);
extern int osd_close(SDL_Event event);
// keyboard event handler
extern int osd_handle(SDL_Event event);
// draw the osd interface, if it's open
extern void osd_present(void);
// future ui
extern void osd_ui_sb_update_icon_state(int tag, int state);
extern void osd_ui_sb_update_icon(int tag, int active);
extern void osd_ui_sb_update_icon_write(int tag, int active);
extern void osd_ui_sb_update_icon_wp(int tag, int state);
#endif /*_UNIX_OSD_H*/

File diff suppressed because it is too large Load Diff

View File

@@ -2316,7 +2316,38 @@ mem_mapping_recalc(uint64_t base, uint64_t size)
if (start < map->base)
start = map->base;
for (i_c = i_s; i_c <= i_e; i_c += i_a) {
if (i_e == 0x00000000ULL) {
for (c = start; c < end; c += MEM_GRANULARITY_SIZE) {
/* CPU */
n = !!in_smm;
wp = _mem_wp[c >> MEM_GRANULARITY_BITS];
if (map->exec && mem_mapping_access_allowed(map->flags,
_mem_state[c >> MEM_GRANULARITY_BITS].states[n].x))
_mem_exec[c >> MEM_GRANULARITY_BITS] = map->exec + (c - map->base);
if (!wp && (map->write_b || map->write_w || map->write_l) &&
mem_mapping_access_allowed(map->flags,
_mem_state[c >> MEM_GRANULARITY_BITS].states[n].w))
write_mapping[c >> MEM_GRANULARITY_BITS] = map;
if ((map->read_b || map->read_w || map->read_l) &&
mem_mapping_access_allowed(map->flags,
_mem_state[c >> MEM_GRANULARITY_BITS].states[n].r))
read_mapping[c >> MEM_GRANULARITY_BITS] = map;
/* Bus */
n |= STATE_BUS;
wp = _mem_wp_bus[c >> MEM_GRANULARITY_BITS];
if (!wp && (map->write_b || map->write_w || map->write_l) &&
mem_mapping_access_allowed(map->flags,
_mem_state[c >> MEM_GRANULARITY_BITS].states[n].w))
write_mapping_bus[c >> MEM_GRANULARITY_BITS] = map;
if ((map->read_b || map->read_w || map->read_l) &&
mem_mapping_access_allowed(map->flags,
_mem_state[c >> MEM_GRANULARITY_BITS].states[n].r))
read_mapping_bus[c >> MEM_GRANULARITY_BITS] = map;
}
} else for (i_c = i_s; i_c <= i_e; i_c += i_a) {
for (c = (start + i_c); c < (end + i_c); c += MEM_GRANULARITY_SIZE) {
/* CPU */
n = (!!in_smm) || (is_cxsmm && (ccr1 & CCR1_SMAC));

View File

@@ -235,7 +235,7 @@ msgid "&New image..."
msgstr "&Nieuw imagebestand..."
msgid "&Existing image..."
msgstr "&Bestaande imagebestand..."
msgstr "&Bestaand imagebestand..."
msgid "Existing image (&Write-protected)..."
msgstr "Bestaand imagebestand (&Schrijfbeveiligd)..."

View File

@@ -1715,12 +1715,12 @@ OpenGLRenderer::render()
plat_tempfile(fn, NULL, (char*)".png");
strcat(path, fn);
unsigned char *rgb = (unsigned char *) calloc(1, (size_t) width * height * 3);
unsigned char *rgb = (unsigned char *) calloc(1, (size_t) width * height * 4);
glw.glFinish();
glw.glReadPixels(window_rect.x, window_rect.y, width, height, GL_RGB, GL_UNSIGNED_BYTE, rgb);
QImage image(rgb, width, height, QImage::Format_RGB888);
QImage image((uchar*)rgb, width, height, width * 3, QImage::Format_RGB888);
image.mirrored(false, true).save(path, "png");
monitors[r_monitor_index].mon_screenshots--;
free(rgb);

View File

@@ -44,6 +44,7 @@ endif()
add_library(ui OBJECT
unix_sdl.c
unix_osd.c
unix_cdrom.c
dummy_cdrom_ioctl.c
)

View File

@@ -41,6 +41,7 @@
#include <86box/device.h>
#include <86box/gameport.h>
#include <86box/unix_sdl.h>
#include <86box/unix_osd.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/nvr.h>
@@ -52,6 +53,8 @@
#define __USE_GNU 1 /* shouldn't be done, yet it is */
#include <pthread.h>
extern SDL_Window *sdl_win;
static int first_use = 1;
static uint64_t StartingTime;
static uint64_t Frequency;
@@ -72,6 +75,10 @@ SDL_threadID eventthread;
static int exit_event = 0;
static int fullscreen_pending = 0;
// Two keys to be pressed together to open the OSD, variables to make them configurable in future
static uint16_t osd_open_first_key = SDL_SCANCODE_RCTRL;
static uint16_t osd_open_second_key = SDL_SCANCODE_F11;
static const uint16_t sdl_to_xt[0x200] = {
[SDL_SCANCODE_ESCAPE] = 0x01,
[SDL_SCANCODE_1] = 0x02,
@@ -291,7 +298,7 @@ plat_get_string(int i)
case STRING_MONITOR_SLEEP:
return L"Monitor in sleep mode";
case STRING_EDID_TOO_LARGE:
return "EDID file \"%ls\" is too large.";
return L"EDID file \"%ls\" is too large.";
}
return L"";
}
@@ -480,22 +487,24 @@ plat_remove(char *path)
remove(path);
}
void
ui_sb_update_icon_state(UNUSED(int tag), UNUSED(int state))
void ui_sb_update_icon_state(int tag, int state)
{
/* No-op. */
osd_ui_sb_update_icon_state(tag, state);
}
void
ui_sb_update_icon(UNUSED(int tag), UNUSED(int active))
void ui_sb_update_icon(int tag, int active)
{
/* No-op. */
osd_ui_sb_update_icon(tag, active);
}
void
ui_sb_update_icon_write(UNUSED(int tag), UNUSED(int active))
void ui_sb_update_icon_write(int tag, int active)
{
/* No-op. */
osd_ui_sb_update_icon_write(tag, active);
}
void ui_sb_update_icon_wp(int tag, int state)
{
osd_ui_sb_update_icon_wp(tag, state);
}
void
@@ -541,7 +550,6 @@ path_get_dirname(char *dest, const char *path)
*dest++ = *path++;
*dest = '\0';
}
volatile int cpu_thread_run = 1;
void
ui_sb_set_text_w(UNUSED(wchar_t *wstr))
@@ -561,6 +569,8 @@ strnicmp(const char *s1, const char *s2, size_t n)
return strncasecmp(s1, s2, n);
}
volatile int cpu_thread_run = 1;
void
main_thread(UNUSED(void *param))
{
@@ -574,15 +584,20 @@ main_thread(UNUSED(void *param))
// title_update = 1;
old_time = SDL_GetTicks();
drawits = frames = 0;
while (!is_quit && cpu_thread_run) {
while (!is_quit && cpu_thread_run)
{
/* See if it is time to run a frame of code. */
new_time = SDL_GetTicks();
#ifdef USE_GDBSTUB
if (gdbstub_next_asap && (drawits <= 0))
drawits = 10;
else
#endif
drawits += (new_time - old_time);
#else
drawits += (new_time - old_time);
#endif
old_time = new_time;
if (drawits > 0 && !dopause) {
/* Yes, so do one frame now. */
@@ -599,15 +614,18 @@ main_thread(UNUSED(void *param))
nvr_dosave = 0;
frames = 0;
}
} else /* Just so we dont overload the host OS. */
}
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, 0);
else
plat_resize(scrnsz_x, scrnsz_y, 0);
atomic_store(&doresize_monitors[0], 1);
}
}
@@ -760,8 +778,6 @@ ui_sb_set_ready(UNUSED(int ready))
/* No-op. */
}
char *xargv[512];
// From musl.
char *
local_strsep(char **str, const char *sep)
@@ -922,7 +938,7 @@ plat_get_vmm_dir(char *outbuf, const size_t len)
}
bool
process_media_commands_3(uint8_t *id, char *fn, uint8_t *wp, int cmdargc)
process_media_commands_3(uint8_t *id, char *fn, uint8_t *wp, char **xargv, int cmdargc)
{
bool err = false;
@@ -958,6 +974,7 @@ process_media_commands_3(uint8_t *id, char *fn, uint8_t *wp, int cmdargc)
fn[strlen(fn) - 1] = '\0';
return err;
}
char *(*f_readline)(const char *) = NULL;
int (*f_add_history)(const char *) = NULL;
void (*f_rl_callback_handler_remove)(void) = NULL;
@@ -968,11 +985,6 @@ void (*f_rl_callback_handler_remove)(void) = NULL;
# define LIBEDIT_LIBRARY "libedit.so"
#endif
void ui_sb_update_icon_wp(int tag, int state)
{
/* No-op */
}
uint32_t
timer_onesec(uint32_t interval, UNUSED(void *param))
{
@@ -981,67 +993,50 @@ timer_onesec(uint32_t interval, UNUSED(void *param))
}
void
monitor_thread(UNUSED(void *param))
unix_executeLine(char *line)
{
#ifndef USE_CLI
if (isatty(fileno(stdin)) && isatty(fileno(stdout))) {
char *line = NULL;
size_t n;
if (line) {
char *xargv[512];
int cmdargc = 0;
char *linecpy, *linespn;
printf("86Box monitor console.\n");
while (!exit_event) {
if (feof(stdin))
linecpy = linespn = strdup(line);
linecpy[strcspn(linecpy, "\r\n")] = 0;
if (!linecpy) {
return;
}
if (f_add_history)
f_add_history(linecpy);
memset(xargv, 0, sizeof(xargv));
while (1) {
xargv[cmdargc++] = local_strsep(&linespn, " ");
if (xargv[cmdargc - 1] == NULL || cmdargc >= 512)
break;
#ifdef ENABLE_READLINE
if (f_readline)
line = f_readline("(86Box) ");
else {
#endif
printf("(86Box) ");
(void) !getline(&line, &n, stdin);
#ifdef ENABLE_READLINE
}
#endif
if (line) {
int cmdargc = 0;
char *linecpy;
line[strcspn(line, "\r\n")] = '\0';
linecpy = strdup(line);
if (!linecpy) {
free(line);
line = NULL;
continue;
}
if (f_add_history)
f_add_history(line);
memset(xargv, 0, sizeof(xargv));
while (1) {
xargv[cmdargc++] = local_strsep(&linecpy, " ");
if (xargv[cmdargc - 1] == NULL || cmdargc >= 512)
break;
}
cmdargc--;
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"
"rdiskload <id> <filename> <wp> - Load removable disk image into removable disk 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"
"rdiskeject <id> - eject removable disk image from removable disk 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");
} else if (strncasecmp(xargv[0], "exit", 4) == 0) {
exit_event = 1;
} else if (strncasecmp(xargv[0], "version", 7) == 0) {
}
cmdargc--;
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"
"rdiskload <id> <filename> <wp> - Load removable disk image into removable disk 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"
"rdiskeject <id> - eject removable disk image from removable disk 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");
} else if (strncasecmp(xargv[0], "exit", 4) == 0) {
exit_event = 1;
} else if (strncasecmp(xargv[0], "version", 7) == 0) {
# ifndef EMU_GIT_HASH
# define EMU_GIT_HASH "0000000"
# endif
@@ -1064,169 +1059,191 @@ monitor_thread(UNUSED(void *param))
# define DYNAREC_STR "no dynarec"
# endif
printf(
"%s v%s [%s] [%s, %s]\n\n"
"An emulator of old computers\n"
"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);
} else if (strncasecmp(xargv[0], "fullscreen", 10) == 0) {
video_fullscreen = video_fullscreen ? 0 : 1;
fullscreen_pending = 1;
} else if (strncasecmp(xargv[0], "pause", 5) == 0) {
plat_pause(dopause ^ 1);
printf("%s", dopause ? "Paused.\n" : "Unpaused.\n");
} 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];
printf(
"%s v%s [%s] [%s, %s]\n\n"
"An emulator of old computers\n"
"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);
} else if (strncasecmp(xargv[0], "fullscreen", 10) == 0) {
video_fullscreen = video_fullscreen ? 0 : 1;
fullscreen_pending = 1;
} else if (strncasecmp(xargv[0], "pause", 5) == 0) {
plat_pause(dopause ^ 1);
printf("%s", dopause ? "Paused.\n" : "Unpaused.\n");
} 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];
if (!xargv[2] || !xargv[1]) {
free(line);
free(linecpy);
line = NULL;
continue;
if (!xargv[2] || !xargv[1]) {
free(linecpy);
return;
}
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");
}
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
{
strcat(fn, xargv[curarg] + (xargv[curarg][0] == '\'' || xargv[curarg][0] == '"'));
if (fn[strlen(fn) - 1] == '\''
|| fn[strlen(fn) - 1] == '"') {
break;
}
} 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';
printf("Inserting disc into CD-ROM drive %hhu: %s\n", id, fn);
cdrom_mount(id, fn);
}
} else if (strncasecmp(xargv[0], "fddeject", 8) == 0 && cmdargc >= 2) {
floppy_eject(atoi(xargv[1]));
} else if (strncasecmp(xargv[0], "cdeject", 8) == 0 && cmdargc >= 2) {
cdrom_mount(atoi(xargv[1]), "");
} else if (strncasecmp(xargv[0], "moeject", 8) == 0 && cmdargc >= 2) {
mo_eject(atoi(xargv[1]));
} else if (strncasecmp(xargv[0], "carteject", 8) == 0 && cmdargc >= 2) {
cartridge_eject(atoi(xargv[1]));
} else if (strncasecmp(xargv[0], "rdiskeject", 8) == 0 && cmdargc >= 2) {
rdisk_eject(atoi(xargv[1]));
} else if (strncasecmp(xargv[0], "fddload", 7) == 0 && cmdargc >= 4) {
uint8_t id;
uint8_t 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 floppy drive %c: %s\n", id + 'A', fn);
floppy_mount(id, fn, wp);
}
} else if (strncasecmp(xargv[0], "moload", 7) == 0 && cmdargc >= 4) {
uint8_t id;
uint8_t 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 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;
uint8_t 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], "rdiskload", 7) == 0 && cmdargc >= 4) {
uint8_t id;
uint8_t 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 removable disk drive %c: %s\n", id + 'A', fn);
rdisk_mount(id, fn, wp);
strcat(fn, " ");
}
}
free(line);
free(linecpy);
line = NULL;
} else {
if (strlen(xargv[2]) < PATH_MAX) {
strncpy(fn, xargv[2], PATH_MAX-1);
} else {
fprintf(stderr, "Path name too long.\n");
}
}
if (!err) {
if (fn[strlen(fn) - 1] == '\''
|| fn[strlen(fn) - 1] == '"')
fn[strlen(fn) - 1] = '\0';
printf("Inserting disc into CD-ROM drive %hhu: %s\n", id, fn);
cdrom_mount(id, fn);
}
} else if (strncasecmp(xargv[0], "fddeject", 8) == 0 && cmdargc >= 2) {
floppy_eject(atoi(xargv[1]));
} else if (strncasecmp(xargv[0], "cdeject", 8) == 0 && cmdargc >= 2) {
cdrom_mount(atoi(xargv[1]), "");
} else if (strncasecmp(xargv[0], "moeject", 8) == 0 && cmdargc >= 2) {
mo_eject(atoi(xargv[1]));
} else if (strncasecmp(xargv[0], "carteject", 8) == 0 && cmdargc >= 2) {
cartridge_eject(atoi(xargv[1]));
} else if (strncasecmp(xargv[0], "rdiskeject", 8) == 0 && cmdargc >= 2) {
rdisk_eject(atoi(xargv[1]));
} else if (strncasecmp(xargv[0], "fddload", 7) == 0 && cmdargc >= 4) {
uint8_t id;
uint8_t wp;
bool err = false;
char fn[PATH_MAX];
memset(fn, 0, sizeof(fn));
if (!xargv[2] || !xargv[1]) {
free(linecpy);
return;
}
err = process_media_commands_3(&id, fn, &wp, xargv, cmdargc);
if (!err) {
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);
}
} else if (strncasecmp(xargv[0], "moload", 7) == 0 && cmdargc >= 4) {
uint8_t id;
uint8_t wp;
bool err = false;
char fn[PATH_MAX];
memset(fn, 0, sizeof(fn));
if (!xargv[2] || !xargv[1]) {
free(linecpy);
return;
}
err = process_media_commands_3(&id, fn, &wp, xargv, cmdargc);
if (!err) {
if (fn[strlen(fn) - 1] == '\''
|| fn[strlen(fn) - 1] == '"')
fn[strlen(fn) - 1] = '\0';
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;
uint8_t wp;
bool err = false;
char fn[PATH_MAX];
memset(fn, 0, sizeof(fn));
if (!xargv[2] || !xargv[1]) {
free(linecpy);
return;
}
err = process_media_commands_3(&id, fn, &wp, xargv, 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], "rdiskload", 7) == 0 && cmdargc >= 4) {
uint8_t id;
uint8_t wp;
bool err = false;
char fn[PATH_MAX];
memset(fn, 0, sizeof(fn));
if (!xargv[2] || !xargv[1]) {
free(linecpy);
return;
}
err = process_media_commands_3(&id, fn, &wp, xargv, cmdargc);
if (!err) {
if (fn[strlen(fn) - 1] == '\''
|| fn[strlen(fn) - 1] == '"')
fn[strlen(fn) - 1] = '\0';
printf("Inserting disk into removable disk drive %c: %s\n", id + 'A', fn);
rdisk_mount(id, fn, wp);
}
}
free(linecpy);
}
}
void
monitor_thread(UNUSED(void *param))
{
#ifndef USE_CLI
if (isatty(fileno(stdin)) && isatty(fileno(stdout))) {
char *line = NULL;
size_t n;
printf("86Box monitor console.\n");
while (!exit_event)
{
if (feof(stdin))
break;
#ifdef ENABLE_READLINE
if (f_readline)
line = f_readline("(86Box) ");
else {
#endif
printf("(86Box) ");
(void) !getline(&line, &n, stdin);
#ifdef ENABLE_READLINE
}
#endif
unix_executeLine(line);
free(line);
line = NULL;
}
}
#endif
@@ -1283,106 +1300,41 @@ main(int argc, char **argv)
plat_pause(0);
/* Initialize the rendering window, or fullscreen. */
do_start();
#ifndef USE_CLI
thread_create(monitor_thread, NULL);
#endif
SDL_AddTimer(1000, timer_onesec, NULL);
while (!is_quit) {
while (!is_quit)
{
static int mouse_inside = 0;
static int osd_first_key_pressed = 0;
static int flag_osd_open = 0;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
exit_event = 1;
break;
case SDL_MOUSEWHEEL:
while (SDL_PollEvent(&event))
{
if (flag_osd_open == 1)
{
// route almost everything to the OSD
switch (event.type)
{
case SDL_QUIT:
{
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);
SDL_UnlockMutex(mousemutex);
}
exit_event = 1;
break;
}
case SDL_MOUSEMOTION:
{
if (mouse_capture || video_fullscreen) {
SDL_LockMutex(mousemutex);
mouse_scale(event.motion.xrel, event.motion.yrel);
SDL_UnlockMutex(mousemutex);
}
break;
}
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
{
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;
}
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;
case SDL_BUTTON_X1:
buttonmask = 8;
break;
case SDL_BUTTON_X2:
buttonmask = 16;
break;
}
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);
SDL_UnlockMutex(mousemutex);
}
break;
}
case SDL_RENDER_DEVICE_RESET:
case SDL_RENDER_TARGETS_RESET:
case SDL_RENDER_DEVICE_RESET:
case SDL_RENDER_TARGETS_RESET:
{
extern void sdl_reinit_texture(void);
printf("reinit tex\n");
sdl_reinit_texture();
break;
}
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);
}
case SDL_WINDOWEVENT:
case SDL_WINDOWEVENT:
{
switch (event.window.event) {
case SDL_WINDOWEVENT_ENTER:
@@ -1392,9 +1344,190 @@ main(int argc, char **argv)
mouse_inside = 0;
break;
}
break;
}
default:
{
// route everything else
flag_osd_open = osd_handle(event);
if (flag_osd_open == 0)
{
// close it
osd_close(event);
}
break;
}
}
}
else
{
switch (event.type)
{
case SDL_QUIT:
exit_event = 1;
break;
case SDL_MOUSEWHEEL:
{
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);
SDL_UnlockMutex(mousemutex);
}
break;
}
case SDL_MOUSEMOTION:
{
if (mouse_capture || video_fullscreen) {
SDL_LockMutex(mousemutex);
mouse_scale(event.motion.xrel, event.motion.yrel);
SDL_UnlockMutex(mousemutex);
}
break;
}
/* Touch events */
case SDL_FINGERDOWN:
{
// Trap these but ignore them for now
break;
}
case SDL_FINGERUP:
{
// Trap these but ignore them for now
break;
}
case SDL_FINGERMOTION:
{
// See SDL_TouchFingerEvent
if (mouse_capture || video_fullscreen) {
SDL_LockMutex(mousemutex);
// Real multiplier is the window size
int w, h;
SDL_GetWindowSize(sdl_win, &w, &h);
mouse_scale((int)(event.tfinger.dx * w), (int)(event.tfinger.dy * h));
SDL_UnlockMutex(mousemutex);
}
break;
}
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
{
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;
}
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;
case SDL_BUTTON_X1:
buttonmask = 8;
break;
case SDL_BUTTON_X2:
buttonmask = 16;
break;
default:
printf("Unknown mouse button %d\n", event.button.button);
}
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);
SDL_UnlockMutex(mousemutex);
}
break;
}
case SDL_RENDER_DEVICE_RESET:
case SDL_RENDER_TARGETS_RESET:
{
extern void sdl_reinit_texture(void);
sdl_reinit_texture();
break;
}
case SDL_KEYDOWN:
case SDL_KEYUP:
{
uint16_t xtkey = 0;
if (event.key.keysym.scancode == osd_open_first_key)
{
if (event.type == SDL_KEYDOWN)
osd_first_key_pressed = 1;
else
osd_first_key_pressed = 0;
}
else if (osd_first_key_pressed && event.type == SDL_KEYDOWN && event.key.keysym.scancode == osd_open_second_key)
{
// open OSD!
flag_osd_open = osd_open(event);
// we can assume alt-gr has been released, tell this also to the virtual machine
osd_first_key_pressed = 0;
keyboard_input(0, sdl_to_xt[osd_open_first_key]);
break;
}
else
{
// invalidate osd_first_key_pressed is something happens between its keydown and keydown for G
osd_first_key_pressed = 0;
}
switch (event.key.keysym.scancode) {
default:
xtkey = sdl_to_xt[event.key.keysym.scancode];
break;
}
keyboard_input(event.key.state == SDL_PRESSED, xtkey);
break;
}
case SDL_WINDOWEVENT:
{
switch (event.window.event) {
case SDL_WINDOWEVENT_ENTER:
mouse_inside = 1;
break;
case SDL_WINDOWEVENT_LEAVE:
mouse_inside = 0;
break;
}
break;
}
default:
{
// printf("Unhandled SDL event: %d\n", event.type);
break;
}
}
}
}
if (blitreq) {
extern void sdl_blit(int x, int y, int w, int h);
sdl_blit(params.x, params.y, params.w, params.h);

View File

@@ -43,13 +43,14 @@ cassette_mount(char *fn, uint8_t wp)
memset(cassette_fname, 0, sizeof(cassette_fname));
cassette_ui_writeprot = wp;
pc_cas_set_fname(cassette, fn);
if (fn != NULL)
memcpy(cassette_fname, fn, MIN(511, strlen(fn)));
ui_sb_update_icon_state(SB_CASSETTE, (fn == NULL) ? 1 : 0);
#if 0
media_menu_update_cassette();
#endif
ui_sb_update_tip(SB_CASSETTE);
config_save();
}
@@ -58,11 +59,11 @@ cassette_eject(void)
{
pc_cas_set_fname(cassette, NULL);
memset(cassette_fname, 0x00, sizeof(cassette_fname));
ui_sb_update_icon_state(SB_CASSETTE, 1);
#if 0
media_menu_update_cassette();
#endif
ui_sb_update_tip(SB_CASSETTE);
config_save();
}
@@ -71,11 +72,11 @@ cartridge_mount(uint8_t id, char *fn, UNUSED(uint8_t wp))
{
cart_close(id);
cart_load(id, fn);
ui_sb_update_icon_state(SB_CARTRIDGE | id, strlen(cart_fns[id]) ? 0 : 1);
#if 0
media_menu_update_cartridge(id);
#endif
ui_sb_update_tip(SB_CARTRIDGE | id);
config_save();
}
@@ -83,11 +84,11 @@ void
cartridge_eject(uint8_t id)
{
cart_close(id);
ui_sb_update_icon_state(SB_CARTRIDGE | id, 1);
#if 0
media_menu_update_cartridge(id);
#endif
ui_sb_update_tip(SB_CARTRIDGE | id);
config_save();
}
@@ -97,11 +98,11 @@ floppy_mount(uint8_t id, char *fn, uint8_t wp)
fdd_close(id);
ui_writeprot[id] = wp;
fdd_load(id, fn);
ui_sb_update_icon_state(SB_FLOPPY | id, strlen(floppyfns[id]) ? 0 : 1);
#if 0
media_menu_update_floppy(id);
#endif
ui_sb_update_tip(SB_FLOPPY | id);
config_save();
}
@@ -109,11 +110,11 @@ void
floppy_eject(uint8_t id)
{
fdd_close(id);
ui_sb_update_icon_state(SB_FLOPPY | id, 1);
#if 0
media_menu_update_floppy(id);
#endif
ui_sb_update_tip(SB_FLOPPY | id);
config_save();
}
@@ -128,34 +129,16 @@ plat_cdrom_ui_update(uint8_t id, UNUSED(uint8_t reload))
ui_sb_update_icon_state(SB_CDROM | id, 0);
}
#if 0
media_menu_update_cdrom(id);
#endif
ui_sb_update_tip(SB_CDROM | id);
}
void
cdrom_mount(uint8_t id, char *fn)
{
strcpy(cdrom[id].prev_image_path, cdrom[id].image_path);
if (cdrom[id].ops && cdrom[id].ops->close)
cdrom[id].ops->close(cdrom[id].local);
cdrom[id].ops = NULL;
memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path));
if ((fn != NULL) && (strlen(fn) >= 1) && (fn[strlen(fn) - 1] == '\\'))
fn[strlen(fn) - 1] = '/';
image_open(&(cdrom[id]), fn);
/* Signal media change to the emulated machine. */
if (cdrom[id].insert)
cdrom[id].insert(cdrom[id].priv);
if (cdrom[id].image_path[0] == 0x00)
ui_sb_update_icon_state(SB_CDROM | id, 0);
else
ui_sb_update_icon_state(SB_CDROM | id, 1);
#if 0
media_menu_update_cdrom(id);
#endif
ui_sb_update_tip(SB_CDROM | id);
int ret = cdrom_load( &(cdrom[id]), fn, 0);
plat_cdrom_ui_update(id, 0);
config_save();
}
@@ -171,9 +154,7 @@ mo_eject(uint8_t id)
}
ui_sb_update_icon_state(SB_MO | id, 1);
#if 0
media_menu_update_mo(id);
#endif
ui_sb_update_tip(SB_MO | id);
config_save();
}
@@ -188,9 +169,7 @@ mo_mount(uint8_t id, char *fn, uint8_t wp)
mo_load(dev, fn, 0);
ui_sb_update_icon_state(SB_MO | id, strlen(mo_drives[id].image_path) ? 0 : 1);
#if 0
media_menu_update_mo(id);
#endif
ui_sb_update_tip(SB_MO | id);
config_save();
@@ -208,9 +187,6 @@ mo_reload(uint8_t id)
ui_sb_update_icon_state(SB_MO | id, 0);
}
#if 0
media_menu_update_mo(id);
#endif
ui_sb_update_tip(SB_MO | id);
config_save();
@@ -228,10 +204,9 @@ rdisk_eject(uint8_t id)
}
ui_sb_update_icon_state(SB_RDISK | id, 1);
#if 0
media_menu_update_rdisk(id);
#endif
ui_sb_update_tip(SB_RDISK | id);
config_save();
}
@@ -245,9 +220,7 @@ rdisk_mount(uint8_t id, char *fn, uint8_t wp)
rdisk_load(dev, fn, 0);
ui_sb_update_icon_state(SB_RDISK | id, strlen(rdisk_drives[id].image_path) ? 0 : 1);
#if 0
media_menu_update_rdisk(id);
#endif
ui_sb_update_tip(SB_RDISK | id);
config_save();
@@ -265,9 +238,6 @@ rdisk_reload(uint8_t id)
ui_sb_update_icon_state(SB_RDISK | id, 0);
}
#if 0
media_menu_update_rdisk(id);
#endif
ui_sb_update_tip(SB_RDISK | id);
config_save();

563
src/unix/unix_osd.c Normal file
View File

@@ -0,0 +1,563 @@
#include <SDL.h>
#include <SDL_messagebox.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <sys/param.h>
/* This #undef is needed because a SDL include header redefines HAVE_STDARG_H. */
#undef HAVE_STDARG_H
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/plat.h>
#include <86box/plat_dynld.h>
#include <86box/video.h>
#include <86box/ui.h>
#include <86box/version.h>
#include <86box/unix_sdl.h>
#include <86box/unix_osd.h>
#include <86box/unix_osd_font.h>
static int SCREEN_W = 640;
static int SCREEN_H = 480;
static int BOX_W = 240;
static int BOX_H = 160;
#define LINE_HEIGHT 16
#define TITLE_HEIGHT 16
#define CHAR_W 8
#define CHAR_H 8
// this makes the osd embeddable in the 86box main sdl loop
#define OSD_INSIDE_MAIN_LOOP
// interface to SDL environment
extern SDL_Window *sdl_win;
extern SDL_Renderer *sdl_render;
extern SDL_mutex *sdl_mutex;
// interface back to main unix monitor implementation
extern void unix_executeLine(char *line);
// interface to the currently set window title, this can't be seen normally in a fullscreen setup
extern wchar_t sdl_win_title[512];
char sdl_win_title_mb[512] = "";
static SDL_Texture *font_texture = NULL;
typedef enum {
STATE_MENU,
STATE_FILESELECT_FLOPPY,
STATE_FILESELECT_CD,
STATE_FILESELECT_RDISK,
STATE_FILESELECT_CART,
STATE_FILESELECT_MO
} AppState;
static const char *menu_items[] = {
"fddload - Load floppy disk image",
"cdload - Load CD-ROM image",
"rdiskload - Load removable disk image",
"cartload - Load cartridge image",
"moload - Load MO image",
"fddeject - eject disk from floppy drive",
"cdeject - eject disc from CD-ROM drive",
"rdiskeject - eject removable disk",
"carteject - eject cartridge",
"moeject - eject image from MO drive",
"hardreset - hard reset the emulated system",
// "pause - pause the the emulated system",
"fullscreen - toggle fullscreen",
"version - print version and license information",
"exit - exit 86Box",
"close OSD"
};
#define MENU_ITEMS (sizeof(menu_items) / sizeof(menu_items[0]))
// chars per cols and rows
static int font_cols = 16;
static int selected = 0;
static int file_selected = 0;
static int scroll_offset = 0;
static int osd_is_open = 0;
static AppState state = STATE_MENU;
static char files[100][1024];
static int file_count = 0;
static int max_visible = 0;
void reset_iso_files(void)
{
file_selected = 0;
scroll_offset = 0;
file_count = 0;
memset(files, 0, sizeof(files));
}
static int endswith(char *s1, char *mask)
{
int ss = strlen(s1);
int sm = strlen(mask);
return ss >= sm && strncasecmp(s1+ss-sm, mask, sm) == 0;
}
int load_iso_files(char *basedir, char files[][1024], int max_files, char *mask)
{
DIR *d;
struct dirent *dir;
int count = file_count;
d = opendir(basedir);
if (!d)
return file_count;
while ((dir = readdir(d)) != NULL && count < max_files)
{
if (endswith(dir->d_name, mask))
{
strcpy(files[count], basedir);
strcat(files[count], "/");
strcat(files[count], dir->d_name);
count++;
}
}
closedir(d);
return count;
}
void draw_text(SDL_Renderer *renderer, const char *text, int x, int y, SDL_Color color)
{
if (!font_texture)
return;
SDL_SetTextureColorMod(font_texture, color.r, color.g, color.b);
int i = 0;
while (text[i])
{
unsigned char c = text[i];
int tx = (c % font_cols) * CHAR_W;
int ty = (c / font_cols) * CHAR_H;
SDL_Rect src = {tx, ty, CHAR_W, CHAR_H};
SDL_Rect dst = {x + i * CHAR_W, y, CHAR_W, CHAR_H};
SDL_RenderCopy(renderer, font_texture, &src, &dst);
i++;
}
}
void draw_box_with_border(SDL_Renderer *renderer, SDL_Rect box)
{
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_RenderDrawRect(renderer, &box);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_Rect inner = {box.x + 2, box.y + 2, box.w - 4, box.h - 4};
SDL_RenderDrawRect(renderer, &inner);
SDL_SetRenderDrawColor(renderer, 0, 0, 128, 255);
SDL_RenderFillRect(renderer, &inner);
}
void draw_menu(SDL_Renderer *renderer, int selected)
{
int x0 = (SCREEN_W - BOX_W) / 2;
int y0 = (SCREEN_H - BOX_H) / 2;
SDL_Rect box = {x0, y0, BOX_W, BOX_H};
draw_box_with_border(renderer, box);
draw_text(renderer, "MAIN MENU", x0 + 20, y0 + 5, (SDL_Color){255,255,255,255});
wcstombs(sdl_win_title_mb, sdl_win_title, 256);
draw_text(renderer, sdl_win_title_mb, x0 + 120, y0 + 5, (SDL_Color){255,255,255,255});
for (int i = 0; i < MENU_ITEMS; i++)
{
int tx = x0 + 20;
int ty = y0 + TITLE_HEIGHT + i * LINE_HEIGHT;
SDL_Color textColor;
SDL_Rect bgRect = {tx - 5, ty - 2, BOX_W - 20, LINE_HEIGHT};
if (i == selected) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderFillRect(renderer, &bgRect);
textColor = (SDL_Color){0, 0, 0, 255};
} else {
textColor = (SDL_Color){255, 255, 0, 255};
}
draw_text(renderer, menu_items[i], tx, ty, textColor);
}
#ifndef OSD_INSIDE_MAIN_LOOP
SDL_RenderPresent(renderer);
#endif
}
void draw_file_selector(SDL_Renderer *renderer,
char *title,
char files[][1024], int file_count,
int selected, int scroll_offset, int max_visible)
{
int x0 = (SCREEN_W - BOX_W) / 2;
int y0 = (SCREEN_H - BOX_H) / 2;
SDL_Rect box = {x0, y0, BOX_W, BOX_H};
draw_box_with_border(renderer, box);
draw_text(renderer, title, x0 + 20, y0 + 5, (SDL_Color){255,255,255,255});
if (file_count == 0) {
draw_text(renderer, "No files.",
x0 + 20, y0 + TITLE_HEIGHT + 10,
(SDL_Color){255, 255, 0, 255});
} else {
for (int i = 0; i < max_visible && (i + scroll_offset) < file_count; i++) {
int index = i + scroll_offset;
int tx = x0 + 20;
int ty = y0 + TITLE_HEIGHT + i * LINE_HEIGHT;
SDL_Color textColor;
SDL_Rect bgRect = {tx - 5, ty - 2, 200, LINE_HEIGHT};
if (index == selected) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderFillRect(renderer, &bgRect);
textColor = (SDL_Color){0, 0, 0, 255};
} else {
textColor = (SDL_Color){255, 255, 0, 255};
}
draw_text(renderer, files[index], tx, ty, textColor);
}
}
#ifndef OSD_INSIDE_MAIN_LOOP
SDL_RenderPresent(renderer);
#endif
}
void osd_init(void)
{
// debug: fprintf(stderr, "OSD INIT\n");
if (font_texture == NULL)
{
// debug: fprintf(stderr, "OSD INIT FONT\n");
// Carica font bitmap (font.bmp 128x128, 16x16 caratteri, 8x8 ciascuno)
SDL_RWops *rwop = SDL_RWFromConstMem(_________font_bmp, _________font_bmp_len);
if (!rwop)
{
fprintf(stderr, "Cannot create a new SDL RW stream: %s\n", SDL_GetError());
return;
}
// auto-closes the stream
SDL_Surface *font_surface = SDL_LoadBMP_RW(rwop, 1);
if (!font_surface) {
fprintf(stderr, "Cannot create a surface using RW stream: %s\n", SDL_GetError());
return;
}
// Imposta trasparenza sul nero puro
SDL_SetColorKey(font_surface, SDL_TRUE, SDL_MapRGB(font_surface->format, 0, 0, 0));
font_texture = SDL_CreateTextureFromSurface(sdl_render, font_surface);
SDL_FreeSurface(font_surface);
}
}
void osd_deinit(void)
{
// nothing to do
// debug: fprintf(stderr, "OSD DEINIT\n");
// will be implicitly freed on exit
// SDL_DestroyTexture(font_texture);
font_texture = NULL;
}
int osd_open(SDL_Event event)
{
// ok opened
// debug: fprintf(stderr, "OSD OPEN\n");
SDL_GetWindowSize(sdl_win, &SCREEN_W, &SCREEN_H);
BOX_W = (SCREEN_W / 4) * 3;
BOX_H = (SCREEN_H / 4) * 3;
max_visible = (BOX_H - TITLE_HEIGHT) / LINE_HEIGHT;
osd_is_open = 1;
return 1;
}
int osd_close(SDL_Event event)
{
// ok closed
// debug: fprintf(stderr, "OSD CLOSE\n");
osd_is_open = 0;
return 1;
}
static void osd_cmd_run(char *c)
{
char *l = calloc(strlen(c)+2, 1);
strcpy(l, c);
unix_executeLine(l);
free(l);
}
void osd_present(void)
{
// shortcut
if (!osd_is_open)
return;
#ifndef OSD_INSIDE_MAIN_LOOP
SDL_LockMutex(sdl_mutex);
#endif
if (state == STATE_MENU) {
draw_menu(sdl_render, selected);
}
else if (state == STATE_FILESELECT_FLOPPY) {
draw_file_selector(sdl_render, "SELECT FLOPPY IMAGE", files, file_count, file_selected, scroll_offset, max_visible);
}
else if (state == STATE_FILESELECT_CD) {
draw_file_selector(sdl_render, "SELECT CD ISO IMAGE", files, file_count, file_selected, scroll_offset, max_visible);
}
else if (state == STATE_FILESELECT_RDISK) {
draw_file_selector(sdl_render, "SELECT REMOVABLE DISK IMAGE", files, file_count, file_selected, scroll_offset, max_visible);
}
else if (state == STATE_FILESELECT_CART) {
draw_file_selector(sdl_render, "SELECT CARTRIDGE IMAGE", files, file_count, file_selected, scroll_offset, max_visible);
}
else if (state == STATE_FILESELECT_MO) {
draw_file_selector(sdl_render, "SELECT MO IMAGE", files, file_count, file_selected, scroll_offset, max_visible);
}
#ifndef OSD_INSIDE_MAIN_LOOP
SDL_UnlockMutex(sdl_mutex);
#endif
}
int osd_handle(SDL_Event event)
{
// debug: fprintf(stderr, "OSD HANDLE\n");
if (event.type == SDL_KEYUP)
{
if (event.key.keysym.scancode == SDL_SCANCODE_ESCAPE)
{
if (state == STATE_MENU)
{
// Close the OSD
// debug: fprintf(stderr, "OSD HANDLE: escape\n");
return 0;
}
else
{
// Back to Main and keep it open
state = STATE_MENU;
return 1;
}
}
if (state == STATE_MENU)
{
switch (event.key.keysym.sym)
{
case SDLK_UP:
selected = (selected - 1 + MENU_ITEMS) % MENU_ITEMS;
break;
case SDLK_DOWN:
selected = (selected + 1) % MENU_ITEMS;
break;
case SDLK_RETURN:
case SDLK_KP_ENTER:
switch (selected)
{
case 0 : // "fddload - Load floppy disk image",
reset_iso_files();
file_count = load_iso_files(".", files, 100, ".img");
file_count = load_iso_files("/mnt", files, 100, ".img");
file_count = load_iso_files("/mnt/usbkey", files, 100, ".img");
state = STATE_FILESELECT_FLOPPY;
break;
case 1 : // "cdload - Load CD-ROM image",
reset_iso_files();
file_count = load_iso_files(".", files, 100, ".iso");
file_count = load_iso_files("/mnt", files, 100, ".iso");
file_count = load_iso_files("/mnt/usbkey", files, 100, ".iso");
state = STATE_FILESELECT_CD;
break;
case 2 : // "rdiskload - Load removable disk image",
reset_iso_files();
file_count = load_iso_files(".", files, 100, ".img");
file_count = load_iso_files("/mnt", files, 100, ".img");
file_count = load_iso_files("/mnt/usbkey", files, 100, ".img");
state = STATE_FILESELECT_RDISK;
break;
case 3 : // "cartload - Load cartridge image",
reset_iso_files();
file_count = load_iso_files(".", files, 100, ".img");
file_count = load_iso_files("/mnt", files, 100, ".img");
file_count = load_iso_files("/mnt/usbkey", files, 100, ".img");
state = STATE_FILESELECT_CART;
break;
case 4 : // "moload - Load MO image",
reset_iso_files();
file_count = load_iso_files(".", files, 100, ".img");
file_count = load_iso_files("/mnt", files, 100, ".img");
file_count = load_iso_files("/mnt/usbkey", files, 100, ".img");
state = STATE_FILESELECT_MO;
break;
case 5 : // "fddeject - eject disk from floppy drive",
osd_cmd_run("fddeject 0");
return 0;
case 6 : // "cdeject - eject disc from CD-ROM drive",
osd_cmd_run("cdeject 0");
return 0;
case 7 : // "rdiskeject - eject removable disk",
osd_cmd_run("rdiskeject 0");
return 0;
case 8 : // "carteject - eject cartridge",
osd_cmd_run("carteject 0");
return 0;
case 9 : // "moeject - eject image from MO drive",
osd_cmd_run("moeject 0");
return 0;
case 10 : // "hardreset - hard reset the emulated system",
osd_cmd_run("hardreset");
return 0;
/* better not pause ourself, we will be unable to get out of it
case 11 : // "pause - pause the the emulated system",
osd_cmd_run("pause");
return 0;
*/
case 11 : // "fullscreen - toggle fullscreen",
osd_cmd_run("fullscreen");
return 0;
case 12 : // "version - print version and license information",
osd_cmd_run("version");
return 0;
case 13 : // "exit - exit 86Box",
osd_cmd_run("exit");
return 0;
case 14 : // "close OSD"
// return zero does directly close the OSD
return 0;
}
break;
}
}
else if (state == STATE_FILESELECT_FLOPPY || state == STATE_FILESELECT_CD || state == STATE_FILESELECT_RDISK || state == STATE_FILESELECT_CART || state == STATE_FILESELECT_MO)
{
if (file_count == 0)
{
// no files, there is nothing else to do
if (event.key.keysym.sym == SDLK_ESCAPE) {
state = STATE_MENU;
}
}
else
{
switch (event.key.keysym.sym) {
case SDLK_UP:
if (file_selected > 0) {
file_selected--;
if (file_selected < scroll_offset) {
scroll_offset--;
}
}
break;
case SDLK_DOWN:
if (file_selected < file_count - 1) {
file_selected++;
if (file_selected >= scroll_offset + max_visible) {
scroll_offset++;
}
}
break;
case SDLK_RETURN:
case SDLK_KP_ENTER:
{
char cmd[1280] = "";
if (state == STATE_FILESELECT_FLOPPY)
sprintf(cmd, "fddload 0 %s 0", files[file_selected]);
if (state == STATE_FILESELECT_CD)
sprintf(cmd, "cdload 0 %s", files[file_selected]);
if (state == STATE_FILESELECT_RDISK)
sprintf(cmd, "rdiskload 0 %s 0", files[file_selected]);
if (state == STATE_FILESELECT_CART)
sprintf(cmd, "cartload 0 %s 0", files[file_selected]);
if (state == STATE_FILESELECT_MO)
sprintf(cmd, "moload 0 %s 0", files[file_selected]);
unix_executeLine(cmd);
state = STATE_MENU;
}
return 0;
case SDLK_ESCAPE:
state = STATE_MENU;
break;
}
}
}
}
// Keep it open
return 1;
}
void osd_ui_sb_update_icon_state(UNUSED(int tag), UNUSED(int state))
{
}
void osd_ui_sb_update_icon(UNUSED(int tag), UNUSED(int active))
{
}
void osd_ui_sb_update_icon_write(UNUSED(int tag), UNUSED(int active))
{
}
void osd_ui_sb_update_icon_wp(UNUSED(int tag), UNUSED(int state))
{
}

View File

@@ -16,6 +16,7 @@
#include <86box/video.h>
#include <86box/ui.h>
#include <86box/version.h>
#include <86box/unix_osd.h>
#include <86box/unix_sdl.h>
#define RENDERER_FULL_SCREEN 1
@@ -45,7 +46,7 @@ static int cur_wy = 0;
static int cur_ww = 0;
static int cur_wh = 0;
static volatile int sdl_enabled = 1;
static SDL_mutex *sdl_mutex = NULL;
SDL_mutex *sdl_mutex = NULL;
int mouse_capture;
int title_set = 0;
int resize_pending = 0;
@@ -189,6 +190,9 @@ sdl_real_blit(SDL_Rect *r_src)
if (ret)
fprintf(stderr, "SDL: unable to copy texture to renderer (%s)\n", SDL_GetError());
// give the osd an opportunity to draw itself
osd_present();
SDL_RenderPresent(sdl_render);
}
@@ -214,6 +218,7 @@ sdl_blit(int x, int y, int w, int h)
sdl_resize(resize_w, resize_h);
resize_pending = 0;
}
r_src.x = x;
r_src.y = y;
r_src.w = w;
@@ -314,6 +319,7 @@ sdl_select_best_hw_driver(void)
void
sdl_reinit_texture(void)
{
osd_deinit();
sdl_destroy_texture();
if (sdl_flags & RENDERER_HARDWARE) {
@@ -324,6 +330,7 @@ sdl_reinit_texture(void)
sdl_tex = SDL_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, 2048, 2048);
osd_init();
}
void
@@ -412,6 +419,10 @@ sdl_init_common(int flags)
return (0);
}
// Ensure mouse and touchpads behaves the same for us, dunno if these really do something
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "1");
SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "1");
if (flags & RENDERER_HARDWARE) {
if (flags & RENDERER_OPENGL) {
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "OpenGL");

View File

@@ -1975,9 +1975,9 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv)
break;
case 0x8190:
virge->streams.sec_ctrl = val;
virge->streams.dda_horiz_accumulator = val & 0xfff;
if (val & 0x1000)
virge->streams.dda_horiz_accumulator |= ~0xfff;
virge->streams.dda_horiz_accumulator = val & 0x7ff;
if (val & 0x800)
virge->streams.dda_horiz_accumulator |= ~0x7ff;
virge->streams.sdif = (val >> 24) & 7;
break;
@@ -1990,9 +1990,9 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv)
if (val & 0x800)
virge->streams.k1_horiz_scale |= ~0x7ff;
virge->streams.k2_horiz_scale = (val >> 16) & 0x7ff;
if ((val >> 16) & 0x800)
virge->streams.k2_horiz_scale |= ~0x7ff;
virge->streams.k2_horiz_scale = (val >> 16) & 0x3ff;
if ((val >> 16) & 0x400)
virge->streams.k2_horiz_scale |= ~0x3ff;
svga_recalctimings(svga);
svga->fullchange = changeframecount;
@@ -2048,14 +2048,14 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv)
virge->streams.k1_vert_scale |= ~0x7ff;
break;
case 0x81e4:
virge->streams.k2_vert_scale = val & 0x7ff;
if (val & 0x800)
virge->streams.k2_vert_scale |= ~0x7ff;
virge->streams.k2_vert_scale = val & 0x3ff;
if (val & 0x400)
virge->streams.k2_vert_scale |= ~0x3ff;
break;
case 0x81e8:
virge->streams.dda_vert_accumulator = val & 0xfff;
if (val & 0x1000)
virge->streams.dda_vert_accumulator |= ~0xfff;
virge->streams.dda_vert_accumulator = val & 0x7ff;
if (val & 0x800)
virge->streams.dda_vert_accumulator |= ~0x7ff;
svga_recalctimings(svga);
svga->fullchange = changeframecount;