Initial Linux/Unix code

This commit is contained in:
Cacodemon345 2021-08-22 16:32:52 +06:00
parent a0c8f9aa9e
commit 1b93e8e989
10 changed files with 1432 additions and 3 deletions

4
.gitignore vendored
View File

@ -10,4 +10,6 @@ src/NUL
src/nvr/
src/roms/
/.vs
/CMakeUserPresets.json
/CMakeUserPresets.json
/build
/.vscode

View File

@ -123,4 +123,9 @@ add_subdirectory(sio)
add_subdirectory(scsi)
add_subdirectory(sound)
add_subdirectory(video)
add_subdirectory(win)
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
add_subdirectory(win)
else()
add_subdirectory(unix)
target_link_libraries(86Box glib-2.0)
endif()

View File

@ -0,0 +1,12 @@
#ifndef _UNIX_SDL_H
#define _UNIX_SDL_H
extern void sdl_close(void);
extern int sdl_inits();
extern int sdl_inith();
extern int sdl_initho();
extern int sdl_pause(void);
extern void sdl_resize(int x, int y);
extern void sdl_enable(int enable);
extern void sdl_set_fs(int fs);
extern void sdl_reload(void);
#endif

View File

@ -17,4 +17,8 @@ add_library(slirp STATIC tinyglib.c arp_table.c bootp.c cksum.c dnssearch.c if.c
ip_input.c ip_output.c mbuf.c misc.c sbuf.c slirp.c socket.c tcp_input.c
tcp_output.c tcp_subr.c tcp_timer.c udp.c util.c version.c)
target_link_libraries(slirp wsock32 iphlpapi)
#target_link_libraries(slirp wsock32 iphlpapi)
#target_link_libraries(slirp)
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
target_link_libraries(wsock32 iphlpapi)
endif()

5
src/unix/CMakeLists.txt Normal file
View File

@ -0,0 +1,5 @@
add_library(plat STATIC unix_thread.c unix_midi.c)
add_library(ui STATIC unix.c unix_sdl.c unix_cdrom.c)
target_compile_definitions(ui PUBLIC _FILE_OFFSET_BITS=64)
target_link_libraries(ui dl)
target_link_libraries(plat pthread)

502
src/unix/unix.c Normal file
View File

@ -0,0 +1,502 @@
#ifdef __linux__
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE64_SOURCE 1
#endif
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <inttypes.h>
#include <dlfcn.h>
#include <SDL2/SDL.h>
#include <86box/86box.h>
#include <86box/config.h>
#include <86box/plat.h>
#include <86box/plat_dynld.h>
#include <86box/device.h>
#include <86box/gameport.h>
#include <86box/unix_sdl.h>
#include <86box/timer.h>
#include <86box/nvr.h>
#include <86box/unix_sdl.h>
static int first_use = 1;
static uint64_t StartingTime;
static uint64_t Frequency;
int rctrl_is_lalt;
int update_icons;
int kbd_req_capture;
int hide_status_bar;
int fixed_size_x = 640;
int fixed_size_y = 480;
plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS];
joystick_t joystick_state[MAX_JOYSTICKS];
int joysticks_present;
SDL_mutex *blitmtx;
typedef struct sdl_blit_params
{
int x, y, y1, y2, w, h;
} sdl_blit_params;
sdl_blit_params params = { 0, 0, 0, 0, 0, 0 };
int blitreq = 0;
void* dynld_module(const char *name, dllimp_t *table)
{
dllimp_t* imp;
void* modhandle = dlopen(name, RTLD_LAZY | RTLD_GLOBAL);
if (modhandle)
{
for (imp = table; imp->name != NULL; imp++)
{
if ((imp->func = dlsym(modhandle, imp->name)) == NULL)
{
dlclose(modhandle);
return NULL;
}
}
}
return modhandle;
}
void
plat_tempfile(char *bufp, char *prefix, char *suffix)
{
struct tm* calendertime;
struct timeval t;
time_t curtime;
if (prefix != NULL)
sprintf(bufp, "%s-", prefix);
else
strcpy(bufp, "");
gettimeofday(&t, NULL);
curtime = time(NULL);
calendertime = localtime(&curtime);
sprintf(&bufp[strlen(bufp)], "%d%02d%02d-%02d%02d%02d-%03d%s", calendertime->tm_year, calendertime->tm_mon, calendertime->tm_mday, calendertime->tm_hour, calendertime->tm_min, calendertime->tm_sec, t.tv_usec / 1000, suffix);
}
int
plat_getcwd(char *bufp, int max)
{
return getcwd(bufp, max) != 0;
}
int
plat_chdir(char* str)
{
return chdir(str);
}
void dynld_close(void *handle)
{
dlclose(handle);
}
wchar_t* plat_get_string(int i)
{
return L"";
}
FILE *
plat_fopen(const char *path, const char *mode)
{
return fopen(path, mode);
}
FILE *
plat_fopen64(const char *path, const char *mode)
{
return fopen(path, mode);
}
int
plat_path_abs(char *path)
{
return path[0] == '/';
}
void
plat_path_slash(char *path)
{
if ((path[strlen(path)-1] != '/')) {
strcat(path, "/");
}
}
void
plat_put_backslash(char *s)
{
int c = strlen(s) - 1;
if (s[c] != '/')
s[c] = '/';
}
/* Return the last element of a pathname. */
char *
plat_get_basename(const char *path)
{
int c = (int)strlen(path);
while (c > 0) {
if (path[c] == '/')
return((char *)&path[c]);
c--;
}
return((char *)path);
}
char *
plat_get_filename(char *s)
{
int c = strlen(s) - 1;
while (c > 0) {
if (s[c] == '/' || s[c] == '\\')
return(&s[c+1]);
c--;
}
return(s);
}
char *
plat_get_extension(char *s)
{
int c = strlen(s) - 1;
if (c <= 0)
return(s);
while (c && s[c] != '.')
c--;
if (!c)
return(&s[strlen(s)]);
return(&s[c+1]);
}
void
plat_append_filename(char *dest, const char *s1, const char *s2)
{
strcpy(dest, s1);
plat_path_slash(dest);
strcat(dest, s2);
}
int
plat_dir_check(char *path)
{
struct stat dummy;
if (stat(path, &dummy) < 0)
{
return 0;
}
return S_ISDIR(dummy.st_mode);
}
int
plat_dir_create(char *path)
{
return mkdir(path, S_IRWXU);
}
uint64_t
plat_timer_read(void)
{
return SDL_GetPerformanceCounter();
}
static uint64_t
plat_get_ticks_common(void)
{
uint64_t EndingTime, ElapsedMicroseconds;
if (first_use) {
Frequency = SDL_GetPerformanceFrequency();
StartingTime = SDL_GetPerformanceCounter();
first_use = 0;
}
EndingTime = SDL_GetPerformanceCounter();
ElapsedMicroseconds = ((EndingTime - StartingTime) * 1000000) / Frequency;
return ElapsedMicroseconds;
}
uint32_t
plat_get_ticks(void)
{
return (uint32_t)(plat_get_ticks_common() / 1000);
}
uint32_t
plat_get_micro_ticks(void)
{
return (uint32_t)plat_get_ticks_common();
}
void plat_remove(char* path)
{
remove(path);
}
void
ui_sb_update_icon_state(int tag, int state)
{
}
void
ui_sb_update_icon(int tag, int active)
{
}
void
plat_delay_ms(uint32_t count)
{
SDL_Delay(count);
}
void
ui_sb_update_tip(int arg)
{
}
void
ui_sb_update_panes()
{
}
void
plat_get_dirname(char *dest, const char *path)
{
int c = (int)strlen(path);
char *ptr;
ptr = (char *)path;
while (c > 0) {
if (path[c] == '/' || path[c] == '\\') {
ptr = (char *)&path[c];
break;
}
c--;
}
/* Copy to destination. */
while (path < ptr)
*dest++ = *path++;
*dest = '\0';
}
volatile int cpu_thread_run = 1;
void ui_sb_set_text_w(wchar_t *wstr)
{
}
int stricmp(const char* s1, const char* s2)
{
return strcasecmp(s1, s2);
}
int strnicmp(const char *s1, const char *s2, size_t n)
{
return strncasecmp(s1, s2, n);
}
void
main_thread(void *param)
{
uint32_t old_time, new_time;
int drawits, frames;
framecountx = 0;
//title_update = 1;
old_time = SDL_GetTicks();
drawits = frames = 0;
while (!is_quit && cpu_thread_run) {
/* See if it is time to run a frame of code. */
new_time = SDL_GetTicks();
drawits += (new_time - old_time);
old_time = new_time;
if (drawits > 0 && !dopause) {
/* Yes, so do one frame now. */
drawits -= 10;
if (drawits > 50)
drawits = 0;
/* Run a block of code. */
pc_run();
/* Every 200 frames we save the machine status. */
if (++frames >= 200 && nvr_dosave) {
nvr_save();
nvr_dosave = 0;
frames = 0;
}
} else /* Just so we dont overload the host OS. */
SDL_Delay(1);
/* If needed, handle a screen resize. */
if (doresize && !video_fullscreen && !is_quit) {
if (vid_resize & 2)
plat_resize(fixed_size_x, fixed_size_y);
else
plat_resize(scrnsz_x, scrnsz_y);
doresize = 0;
}
}
is_quit = 1;
}
thread_t* thMain = NULL;
void mouse_poll()
{}
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)
{
/* Claim the video blitter. */
startblit();
sdl_close();
pc_close(thMain);
thMain = NULL;
}
int ui_msgbox(int flags, void *message)
{
return 0;
}
int ui_msgbox_header(int flags, void *message, void* header)
{
// Parameters that are passed will crash the program so keep these off for the time being.
return 0;
}
void plat_get_exe_name(char *s, int size)
{
char* basepath = SDL_GetBasePath();
snprintf(s, size, "%s/86box", basepath);
}
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;
}
wchar_t* ui_sb_bugui(wchar_t *str)
{
return str;
}
extern void sdl_blit(int x, int y, int y1, int y2, int w, int h);
void ui_window_title(wchar_t* str) {}
void ui_sb_set_ready(int ready) {}
int main(int argc, char** argv)
{
SDL_Event event;
SDL_Init(0);
pc_init(argc, argv);
if (! pc_init_modules()) {
fprintf(stderr, "No ROMs found.\n");
SDL_Quit();
return 6;
}
blitmtx = SDL_CreateMutex();
if (!blitmtx)
{
fprintf(stderr, "Failed to create blit mutex: %s", SDL_GetError());
return -1;
}
sdl_initho();
if (start_in_fullscreen)
sdl_set_fs(1);
/* Fire up the machine. */
pc_reset_hard_init();
/* Set the PAUSE mode depending on the renderer. */
//plat_pause(0);
/* Initialize the rendering window, or fullscreen. */
do_start();
while (!is_quit)
{
if (SDL_PollEvent(&event))
switch(event.type)
{
case SDL_QUIT:
do_stop();
break;
}
if (blitreq)
{
extern void sdl_blit(int x, int y, int y1, int y2, int w, int h);
sdl_blit(params.x, params.y, params.y1, params.y2, params.w, params.h);
}
}
SDL_DestroyMutex(blitmtx);
SDL_Quit();
return 0;
}
char* plat_vidapi_name(int i)
{
return "default";
}
void joystick_init(void) {}
void joystick_close(void) {}
void joystick_process(void) {}
void startblit()
{
SDL_LockMutex(blitmtx);
}
void endblit()
{
SDL_UnlockMutex(blitmtx);
}

264
src/unix/unix_cdrom.c Normal file
View File

@ -0,0 +1,264 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Handle the platform-side of CDROM/ZIP/MO drives.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2016-2018 Miran Grca.
* Copyright 2017,2018 Fred N. van Kempen.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/config.h>
#include <86box/timer.h>
#include <86box/device.h>
#include <86box/cassette.h>
#include <86box/cartridge.h>
#include <86box/fdd.h>
#include <86box/hdd.h>
#include <86box/scsi_device.h>
#include <86box/cdrom.h>
#include <86box/mo.h>
#include <86box/zip.h>
#include <86box/scsi_disk.h>
#include <86box/plat.h>
#include <86box/ui.h>
void
cassette_mount(char *fn, uint8_t wp)
{
pc_cas_set_fname(cassette, NULL);
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);
//media_menu_update_cassette();
ui_sb_update_tip(SB_CASSETTE);
config_save();
}
void
cassette_eject(void)
{
pc_cas_set_fname(cassette, NULL);
memset(cassette_fname, 0x00, sizeof(cassette_fname));
ui_sb_update_icon_state(SB_CASSETTE, 1);
//media_menu_update_cassette();
ui_sb_update_tip(SB_CASSETTE);
config_save();
}
void
cartridge_mount(uint8_t id, char *fn, uint8_t wp)
{
cart_close(id);
cart_load(id, fn);
ui_sb_update_icon_state(SB_CARTRIDGE | id, strlen(cart_fns[id]) ? 0 : 1);
//media_menu_update_cartridge(id);
ui_sb_update_tip(SB_CARTRIDGE | id);
config_save();
}
void
cartridge_eject(uint8_t id)
{
cart_close(id);
ui_sb_update_icon_state(SB_CARTRIDGE | id, 1);
//media_menu_update_cartridge(id);
ui_sb_update_tip(SB_CARTRIDGE | id);
config_save();
}
void
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);
//media_menu_update_floppy(id);
ui_sb_update_tip(SB_FLOPPY | id);
config_save();
}
void
floppy_eject(uint8_t id)
{
fdd_close(id);
ui_sb_update_icon_state(SB_FLOPPY | id, 1);
//media_menu_update_floppy(id);
ui_sb_update_tip(SB_FLOPPY | id);
config_save();
}
void
plat_cdrom_ui_update(uint8_t id, uint8_t reload)
{
cdrom_t *drv = &cdrom[id];
if (drv->host_drive == 0) {
ui_sb_update_icon_state(SB_CDROM|id, 1);
} else {
ui_sb_update_icon_state(SB_CDROM|id, 0);
}
//media_menu_update_cdrom(id);
ui_sb_update_tip(SB_CDROM|id);
}
void
cdrom_mount(uint8_t id, char *fn)
{
cdrom[id].prev_host_drive = cdrom[id].host_drive;
strcpy(cdrom[id].prev_image_path, cdrom[id].image_path);
if (cdrom[id].ops && cdrom[id].ops->exit)
cdrom[id].ops->exit(&(cdrom[id]));
cdrom[id].ops = NULL;
memset(cdrom[id].image_path, 0, sizeof(cdrom[id].image_path));
cdrom_image_open(&(cdrom[id]), fn);
/* Signal media change to the emulated machine. */
if (cdrom[id].insert)
cdrom[id].insert(cdrom[id].priv);
cdrom[id].host_drive = (strlen(cdrom[id].image_path) == 0) ? 0 : 200;
if (cdrom[id].host_drive == 200) {
ui_sb_update_icon_state(SB_CDROM | id, 0);
} else {
ui_sb_update_icon_state(SB_CDROM | id, 1);
}
//media_menu_update_cdrom(id);
ui_sb_update_tip(SB_CDROM | id);
config_save();
}
void
mo_eject(uint8_t id)
{
mo_t *dev = (mo_t *) mo_drives[id].priv;
mo_disk_close(dev);
if (mo_drives[id].bus_type) {
/* Signal disk change to the emulated machine. */
mo_insert(dev);
}
ui_sb_update_icon_state(SB_MO | id, 1);
//media_menu_update_mo(id);
ui_sb_update_tip(SB_MO | id);
config_save();
}
void
mo_mount(uint8_t id, char *fn, uint8_t wp)
{
mo_t *dev = (mo_t *) mo_drives[id].priv;
mo_disk_close(dev);
mo_drives[id].read_only = wp;
mo_load(dev, fn);
mo_insert(dev);
ui_sb_update_icon_state(SB_MO | id, strlen(mo_drives[id].image_path) ? 0 : 1);
//media_menu_update_mo(id);
ui_sb_update_tip(SB_MO | id);
config_save();
}
void
mo_reload(uint8_t id)
{
mo_t *dev = (mo_t *) mo_drives[id].priv;
mo_disk_reload(dev);
if (strlen(mo_drives[id].image_path) == 0) {
ui_sb_update_icon_state(SB_MO|id, 1);
} else {
ui_sb_update_icon_state(SB_MO|id, 0);
}
//media_menu_update_mo(id);
ui_sb_update_tip(SB_MO|id);
config_save();
}
void
zip_eject(uint8_t id)
{
zip_t *dev = (zip_t *) zip_drives[id].priv;
zip_disk_close(dev);
if (zip_drives[id].bus_type) {
/* Signal disk change to the emulated machine. */
zip_insert(dev);
}
ui_sb_update_icon_state(SB_ZIP | id, 1);
//media_menu_update_zip(id);
ui_sb_update_tip(SB_ZIP | id);
config_save();
}
void
zip_mount(uint8_t id, char *fn, uint8_t wp)
{
zip_t *dev = (zip_t *) zip_drives[id].priv;
zip_disk_close(dev);
zip_drives[id].read_only = wp;
zip_load(dev, fn);
zip_insert(dev);
ui_sb_update_icon_state(SB_ZIP | id, strlen(zip_drives[id].image_path) ? 0 : 1);
//media_menu_update_zip(id);
ui_sb_update_tip(SB_ZIP | id);
config_save();
}
void
zip_reload(uint8_t id)
{
zip_t *dev = (zip_t *) zip_drives[id].priv;
zip_disk_reload(dev);
if (strlen(zip_drives[id].image_path) == 0) {
ui_sb_update_icon_state(SB_ZIP|id, 1);
} else {
ui_sb_update_icon_state(SB_ZIP|id, 0);
}
//media_menu_update_zip(id);
ui_sb_update_tip(SB_ZIP|id);
config_save();
}

57
src/unix/unix_midi.c Normal file
View File

@ -0,0 +1,57 @@
#include <inttypes.h>
void plat_midi_init(void)
{
}
void plat_midi_close(void)
{
}
void plat_midi_play_msg(uint8_t *msg)
{
}
void plat_midi_play_sysex(uint8_t *sysex, unsigned int len)
{
}
int plat_midi_write(uint8_t val)
{
return 0;
}
int plat_midi_get_num_devs(void)
{
return 0;
}
void plat_midi_get_dev_name(int num, char *s)
{
s[0] = ' ';
s[1] = 0;
}
void plat_midi_input_init(void)
{
}
void plat_midi_input_close(void)
{
}
int plat_midi_in_get_num_devs(void)
{
return 0;
}
void plat_midi_in_get_dev_name(int num, char *s)
{
s[0] = ' ';
s[1] = 0;
}

420
src/unix/unix_sdl.c Normal file
View File

@ -0,0 +1,420 @@
#include <SDL2/SDL.h>
#include <SDL2/SDL_messagebox.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.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>
#define RENDERER_FULL_SCREEN 1
#define RENDERER_HARDWARE 2
#define RENDERER_OPENGL 4
typedef struct sdl_blit_params
{
int x, y, y1, y2, w, h;
} sdl_blit_params;
extern sdl_blit_params params;
extern int blitreq;
static SDL_Window *sdl_win = NULL;
static SDL_Renderer *sdl_render = NULL;
static SDL_Texture *sdl_tex = NULL;
static int sdl_w, sdl_h;
static int sdl_fs, sdl_flags = -1;
static int cur_w, cur_h;
static int cur_wx = 0, cur_wy = 0, cur_ww =0, cur_wh = 0;
static volatile int sdl_enabled = 1;
static SDL_mutex* sdl_mutex = NULL;
int mouse_capture;
static void
sdl_integer_scale(double *d, double *g)
{
double ratio;
if (*d > *g) {
ratio = floor(*d / *g);
*d = *g * ratio;
} else {
ratio = ceil(*d / *g);
*d = *g / ratio;
}
}
void sdl_reinit_texture();
static void
sdl_stretch(int *w, int *h, int *x, int *y)
{
double hw, gw, hh, gh, dx, dy, dw, dh, gsr, hsr;
hw = (double) sdl_w;
hh = (double) sdl_h;
gw = (double) *w;
gh = (double) *h;
hsr = hw / hh;
switch (video_fullscreen_scale) {
case FULLSCR_SCALE_FULL:
default:
*w = sdl_w;
*h = sdl_h;
*x = 0;
*y = 0;
break;
case FULLSCR_SCALE_43:
case FULLSCR_SCALE_KEEPRATIO:
if (video_fullscreen_scale == FULLSCR_SCALE_43)
gsr = 4.0 / 3.0;
else
gsr = gw / gh;
if (gsr <= hsr) {
dw = hh * gsr;
dh = hh;
} else {
dw = hw;
dh = hw / gsr;
}
dx = (hw - dw) / 2.0;
dy = (hh - dh) / 2.0;
*w = (int) dw;
*h = (int) dh;
*x = (int) dx;
*y = (int) dy;
break;
case FULLSCR_SCALE_INT:
gsr = gw / gh;
if (gsr <= hsr) {
dw = hh * gsr;
dh = hh;
} else {
dw = hw;
dh = hw / gsr;
}
sdl_integer_scale(&dw, &gw);
sdl_integer_scale(&dh, &gh);
dx = (hw - dw) / 2.0;
dy = (hh - dh) / 2.0;
*w = (int) dw;
*h = (int) dh;
*x = (int) dx;
*y = (int) dy;
break;
}
}
void
sdl_blit_shim(int x, int y, int y1, int y2, int w, int h)
{
params.x = x;
params.y = y;
params.w = w;
params.h = h;
params.y1 = y1;
params.y2 = y2;
blitreq = 1;
}
void
sdl_blit(int x, int y, int y1, int y2, int w, int h)
{
SDL_Rect r_src;
int ret;
if (!sdl_enabled || (y1 == y2) || (h <= 0) || (render_buffer == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) {
video_blit_complete();
return;
}
SDL_LockMutex(sdl_mutex);
r_src.x = 0;
r_src.y = y1;
r_src.w = w;
r_src.h = y2 - y1;
SDL_UpdateTexture(sdl_tex, &r_src, &(render_buffer->dat)[y1 * w], w * 4);
video_blit_complete();
SDL_RenderClear(sdl_render);
r_src.x = 0;
r_src.y = 0;
r_src.w = w;
r_src.h = h;
ret = SDL_RenderCopy(sdl_render, sdl_tex, &r_src, 0);
if (ret)
fprintf(stderr, "SDL: unable to copy texture to renderer (%s)\n", SDL_GetError());
SDL_RenderPresent(sdl_render);
SDL_UnlockMutex(sdl_mutex);
}
static void
sdl_destroy_window(void)
{
if (sdl_win != NULL) {
SDL_DestroyWindow(sdl_win);
sdl_win = NULL;
}
}
static void
sdl_destroy_texture(void)
{
/* SDL_DestroyRenderer also automatically destroys all associated textures. */
if (sdl_render != NULL) {
SDL_DestroyRenderer(sdl_render);
sdl_render = NULL;
}
}
void
sdl_close(void)
{
SDL_LockMutex(sdl_mutex);
/* Unregister our renderer! */
video_setblit(NULL);
if (sdl_enabled)
sdl_enabled = 0;
if (sdl_mutex != NULL) {
SDL_DestroyMutex(sdl_mutex);
sdl_mutex = NULL;
}
sdl_destroy_texture();
sdl_destroy_window();
/* Quit. */
SDL_Quit();
sdl_flags = -1;
}
static int old_capture = 0;
void
sdl_enable(int enable)
{
if (sdl_flags == -1)
return;
SDL_LockMutex(sdl_mutex);
sdl_enabled = !!enable;
if (enable == 1) {
SDL_SetWindowSize(sdl_win, cur_ww, cur_wh);
sdl_reinit_texture();
}
SDL_UnlockMutex(sdl_mutex);
}
static void
sdl_select_best_hw_driver(void)
{
int i;
SDL_RendererInfo renderInfo;
for (i = 0; i < SDL_GetNumRenderDrivers(); ++i)
{
SDL_GetRenderDriverInfo(i, &renderInfo);
if (renderInfo.flags & SDL_RENDERER_ACCELERATED) {
SDL_SetHint(SDL_HINT_RENDER_DRIVER, renderInfo.name);
return;
}
}
}
void
sdl_reinit_texture()
{
if (sdl_flags == -1)
return;
sdl_destroy_texture();
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
if (sdl_flags & RENDERER_HARDWARE) {
sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_ACCELERATED);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0");
} else
sdl_render = SDL_CreateRenderer(sdl_win, -1, SDL_RENDERER_SOFTWARE);
sdl_tex = SDL_CreateTexture(sdl_render, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, 2048, 2048);
}
void
sdl_set_fs(int fs)
{
SDL_LockMutex(sdl_mutex);
sdl_enabled = 0;
sdl_destroy_texture();
SDL_SetWindowFullscreen(sdl_win, fs ? SDL_WINDOW_FULLSCREEN : 0);
SDL_SetWindowMouseGrab(sdl_win, mouse_capture);
sdl_fs = fs;
if (fs)
sdl_flags |= RENDERER_FULL_SCREEN;
else
sdl_flags &= ~RENDERER_FULL_SCREEN;
sdl_reinit_texture();
sdl_enabled = 1;
SDL_UnlockMutex(sdl_mutex);
}
void
sdl_resize(int x, int y)
{
int ww = 0, wh = 0, wx = 0, wy = 0;
if (video_fullscreen & 2)
return;
if ((x == cur_w) && (y == cur_h))
return;
SDL_LockMutex(sdl_mutex);
ww = x;
wh = y;
cur_w = x;
cur_h = y;
cur_wx = wx;
cur_wy = wy;
cur_ww = ww;
cur_wh = wh;
SDL_SetWindowSize(sdl_win, cur_ww, cur_wh);
SDL_SetWindowPosition(sdl_win, cur_wx, cur_wy);
sdl_reinit_texture();
SDL_UnlockMutex(sdl_mutex);
}
void
sdl_reload(void)
{
if (sdl_flags & RENDERER_HARDWARE)
{
SDL_LockMutex(sdl_mutex);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, video_filter_method ? "1" : "0");
sdl_reinit_texture();
SDL_UnlockMutex(sdl_mutex);
}
}
int
plat_vidapi(char* api)
{
return 0;
}
static int
sdl_init_common(int flags)
{
wchar_t temp[128];
SDL_version ver;
/* Get and log the version of the DLL we are using. */
SDL_GetVersion(&ver);
fprintf(stderr, "SDL: version %d.%d.%d\n", ver.major, ver.minor, ver.patch);
/* Initialize the SDL system. */
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "SDL: initialization failed (%s)\n", SDL_GetError());
return(0);
}
if (flags & RENDERER_HARDWARE) {
if (flags & RENDERER_OPENGL) {
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "OpenGL");
}
else
sdl_select_best_hw_driver();
}
sdl_mutex = SDL_CreateMutex();
sdl_win = SDL_CreateWindow("86Box", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, scrnsz_x, scrnsz_y, SDL_WINDOW_OPENGL);
sdl_set_fs(video_fullscreen & 1);
if (!(video_fullscreen & 1))
{
if (vid_resize & 2)
plat_resize(fixed_size_x, fixed_size_y);
else
plat_resize(scrnsz_x, scrnsz_y);
}
/* Make sure we get a clean exit. */
atexit(sdl_close);
/* Register our renderer! */
video_setblit(sdl_blit_shim);
sdl_enabled = 1;
return(1);
}
int
sdl_inits()
{
return sdl_init_common(0);
}
int
sdl_inith()
{
return sdl_init_common(RENDERER_HARDWARE);
}
int
sdl_initho()
{
return sdl_init_common(RENDERER_HARDWARE | RENDERER_OPENGL);
}
int
sdl_pause(void)
{
return(0);
}
void
plat_mouse_capture(int on)
{
SDL_LockMutex(sdl_mutex);
SDL_SetWindowMouseGrab(sdl_win, (SDL_bool)on);
SDL_UnlockMutex(sdl_mutex);
}
void plat_resize(int w, int h)
{
SDL_SetWindowSize(sdl_win, w, h);
}

158
src/unix/unix_thread.c Normal file
View File

@ -0,0 +1,158 @@
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <sys/param.h>
#include <unistd.h>
#include <inttypes.h>
#include <86box/86box.h>
#include <86box/plat.h>
typedef struct event_pthread_t
{
pthread_cond_t cond;
pthread_mutex_t mutex;
int state;
} event_pthread_t;
thread_t *thread_create(void (*thread_rout)(void *param), void *param)
{
pthread_t *thread = malloc(sizeof(pthread_t));
pthread_create(thread, NULL, (void*)thread_rout, param);
return thread;
}
int
thread_wait(thread_t *arg, int timeout)
{
return pthread_join(*(pthread_t*)(arg), NULL) != 0;
}
event_t *thread_create_event()
{
event_pthread_t *event = malloc(sizeof(event_pthread_t));
pthread_cond_init(&event->cond, NULL);
pthread_mutex_init(&event->mutex, NULL);
event->state = 0;
return (event_t *)event;
}
void thread_set_event(event_t *handle)
{
event_pthread_t *event = (event_pthread_t *)handle;
pthread_mutex_lock(&event->mutex);
event->state = 1;
pthread_cond_broadcast(&event->cond);
pthread_mutex_unlock(&event->mutex);
}
void thread_reset_event(event_t *handle)
{
event_pthread_t *event = (event_pthread_t *)handle;
pthread_mutex_lock(&event->mutex);
event->state = 0;
pthread_mutex_unlock(&event->mutex);
}
int thread_wait_event(event_t *handle, int timeout)
{
event_pthread_t *event = (event_pthread_t *)handle;
struct timespec abstime;
#if defined __linux__ || defined BSD
clock_gettime(CLOCK_REALTIME, &abstime);
#else
struct timeval now;
gettimeofday(&now, 0);
abstime.tv_sec = now.tv_sec;
abstime.tv_nsec = now.tv_usec*1000UL;
#endif
abstime.tv_nsec += (timeout % 1000) * 1000000;
abstime.tv_sec += (timeout / 1000);
if (abstime.tv_nsec > 1000000000)
{
abstime.tv_nsec -= 1000000000;
abstime.tv_sec++;
}
pthread_mutex_lock(&event->mutex);
if (timeout == -1)
{
while (!event->state)
pthread_cond_wait(&event->cond, &event->mutex);
}
else if (!event->state)
pthread_cond_timedwait(&event->cond, &event->mutex, &abstime);
pthread_mutex_unlock(&event->mutex);
return 0;
}
void thread_destroy_event(event_t *handle)
{
event_pthread_t *event = (event_pthread_t *)handle;
pthread_cond_destroy(&event->cond);
pthread_mutex_destroy(&event->mutex);
free(event);
}
void thread_sleep(int t)
{
usleep(t * 1000);
}
typedef struct pt_mutex_t
{
pthread_mutex_t mutex;
} pt_mutex_t;
mutex_t *thread_create_mutex(void)
{
pt_mutex_t *mutex = malloc(sizeof(pt_mutex_t));
pthread_mutex_init(&mutex->mutex, NULL);
return mutex;
}
mutex_t *
thread_create_mutex_with_spin_count(unsigned int spin_count)
{
/* Setting spin count of a mutex is not possible with pthreads. */
return thread_create_mutex();
}
int thread_wait_mutex(mutex_t *_mutex)
{
if (_mutex == NULL) return(0);
pt_mutex_t *mutex = (pt_mutex_t *)_mutex;
return pthread_mutex_lock(&mutex->mutex) != 0;
}
int thread_release_mutex(mutex_t *_mutex)
{
if (_mutex == NULL) return(0);
pt_mutex_t *mutex = (pt_mutex_t *)_mutex;
return pthread_mutex_unlock(&mutex->mutex) != 0;
}
void thread_close_mutex(mutex_t *_mutex)
{
pt_mutex_t *mutex = (pt_mutex_t *)_mutex;
pthread_mutex_destroy(&mutex->mutex);
free(mutex);
}