502 lines
8.7 KiB
C
502 lines
8.7 KiB
C
#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 ((*(void**)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);
|
|
} |