mirror of
https://github.com/DrBeef/Raze.git
synced 2025-03-05 08:51:02 +00:00
New Wii control defaults for the Wii Remote + Nunchuk and the Classic Controller. This includes new code added just so that the Home key brings up the menu in-game, reducing the need for a USB keyboard. On the technical side, raw joystick access (comparable to what is available for keyboard and mouse) is now present in jmact, on the game side. (added: joystick.[ch]) Using this new raw joystick access, I replaced tueidj's hack to map A and B to LMB/RMB and D-Pad Up/Down to the scrollwheel. I made the menus more friendly to mouse and joystick browsing by adding and unifying checks and clears for various buttons and gamefuncs. In fact, the majority of the time spent on this commit was tracking down problems that appeared with the factoring and trying to understand the menu system and the way input checks are precariously executed. In addition, "Press any key or button to continue" now truly means what it says. As a result of incorporating proper raw access into control.c instead of it directly accessing the implementaiton, the program *may* no longer be affected by joystick input when it is out of focus. This follows the pattern set by the mouse, and I think this is a positive change. A small bonus: In the classic/old keyboard preset, the key for Show_Console has been changed from '`' to 'C' because '`' is taken by Quick_Kick. git-svn-id: https://svn.eduke32.com/eduke32@2728 1a8010ca-5511-0410-912e-c29ae57300e0
2326 lines
60 KiB
C
2326 lines
60 KiB
C
// SDL interface layer
|
|
// for the Build Engine
|
|
// by Jonathon Fowler (jf@jonof.id.au)
|
|
//
|
|
// Use SDL 1.2 or 1.3 from http://www.libsdl.org
|
|
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <signal.h>
|
|
#include "sdl_inc.h"
|
|
#include "compat.h"
|
|
#include "sdlayer.h"
|
|
#include "cache1d.h"
|
|
//#include "pragmas.h"
|
|
#include "a.h"
|
|
#include "build.h"
|
|
#include "osd.h"
|
|
|
|
#if (SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION < 3) // SDL 1.2
|
|
// for SDL_WaitEventTimeout defined below
|
|
#include <SDL/SDL_events.h>
|
|
#endif
|
|
|
|
#ifdef USE_OPENGL
|
|
# include "glbuild.h"
|
|
#endif
|
|
|
|
#if defined __APPLE__
|
|
# include "osxbits.h"
|
|
#elif defined HAVE_GTK2
|
|
# include "gtkbits.h"
|
|
#endif
|
|
|
|
#if (!defined __APPLE__ && !defined HAVE_GTK2) || (defined __APPLE__) // && defined __BIG_ENDIAN__)
|
|
#undef UNREFERENCED_PARAMETER
|
|
#define UNREFERENCED_PARAMETER(x) x=x
|
|
|
|
# ifndef OSX_STARTUPWINDOW
|
|
int32_t startwin_open(void) { return 0; }
|
|
int32_t startwin_close(void) { return 0; }
|
|
int32_t startwin_puts(const char *s) { UNREFERENCED_PARAMETER(s); return 0; }
|
|
int32_t startwin_idle(void *s) { UNREFERENCED_PARAMETER(s); return 0; }
|
|
int32_t startwin_settitle(const char *s) { UNREFERENCED_PARAMETER(s); return 0; }
|
|
# endif
|
|
#endif
|
|
|
|
/// These can be useful for debugging sometimes...
|
|
//#define SDL_WM_GrabInput(x) SDL_WM_GrabInput(SDL_GRAB_OFF)
|
|
//#define SDL_ShowCursor(x) SDL_ShowCursor(SDL_ENABLE)
|
|
|
|
#define SURFACE_FLAGS (SDL_SWSURFACE|SDL_HWPALETTE|SDL_HWACCEL)
|
|
|
|
// undefine to restrict windowed resolutions to conventional sizes
|
|
#define ANY_WINDOWED_SIZE
|
|
|
|
// fix for mousewheel
|
|
#define MWHEELTICKS 10
|
|
static uint32_t mwheelup, mwheeldown;
|
|
|
|
int32_t _buildargc = 1;
|
|
const char **_buildargv = NULL;
|
|
extern int32_t app_main(int32_t argc, const char *argv[]);
|
|
|
|
char quitevent=0, appactive=1, novideo=0;
|
|
|
|
// video
|
|
static SDL_Surface *sdl_surface;
|
|
int32_t xres=-1, yres=-1, bpp=0, fullscreen=0, bytesperline;
|
|
intptr_t frameplace=0;
|
|
int32_t lockcount=0;
|
|
char modechange=1;
|
|
char offscreenrendering=0;
|
|
char videomodereset = 0;
|
|
char nofog=0;
|
|
static uint16_t sysgamma[3][256];
|
|
extern int32_t curbrightness, gammabrightness;
|
|
#ifdef USE_OPENGL
|
|
// OpenGL stuff
|
|
char nogl=0;
|
|
#endif
|
|
int32_t vsync=0;
|
|
|
|
// last gamma, contrast, brightness
|
|
static float lastvidgcb[3];
|
|
|
|
//#define KEY_PRINT_DEBUG
|
|
|
|
#if (SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION < 3)
|
|
static char keytranslation[SDLK_LAST];
|
|
#else
|
|
static char keytranslation[SDL_NUM_SCANCODES];
|
|
#endif
|
|
static int32_t buildkeytranslationtable(void);
|
|
|
|
//static SDL_Surface * loadtarga(const char *fn); // for loading the icon
|
|
static SDL_Surface *appicon = NULL;
|
|
static SDL_Surface *loadappicon(void);
|
|
|
|
static mutex_t m_initprintf;
|
|
|
|
// Joystick dead and saturation zones
|
|
uint16_t *joydead, *joysatur;
|
|
|
|
int32_t wm_msgbox(char *name, char *fmt, ...)
|
|
{
|
|
char buf[2048];
|
|
va_list va;
|
|
|
|
UNREFERENCED_PARAMETER(name);
|
|
|
|
va_start(va,fmt);
|
|
vsprintf(buf,fmt,va);
|
|
va_end(va);
|
|
|
|
#if defined(__APPLE__)
|
|
return osx_msgbox(name, buf);
|
|
#elif defined HAVE_GTK2
|
|
if (gtkbuild_msgbox(name, buf) >= 0) return 1;
|
|
#endif
|
|
puts(buf);
|
|
puts(" (press Return or Enter to continue)");
|
|
getchar();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t wm_ynbox(char *name, char *fmt, ...)
|
|
{
|
|
char buf[2048];
|
|
char c;
|
|
va_list va;
|
|
#if (!defined(__APPLE__) && defined(HAVE_GTK2))
|
|
int32_t r;
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER(name);
|
|
|
|
va_start(va,fmt);
|
|
vsprintf(buf,fmt,va);
|
|
va_end(va);
|
|
|
|
#if defined __APPLE__
|
|
return osx_ynbox(name, buf);
|
|
#elif defined HAVE_GTK2
|
|
if ((r = gtkbuild_ynbox(name, buf)) >= 0) return r;
|
|
#endif
|
|
puts(buf);
|
|
puts(" (type 'Y' or 'N', and press Return or Enter to continue)");
|
|
do c = getchar(); while (c != 'Y' && c != 'y' && c != 'N' && c != 'n');
|
|
if (c == 'Y' || c == 'y') return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void wm_setapptitle(char *name)
|
|
{
|
|
if (name)
|
|
Bstrncpyz(apptitle, name, sizeof(apptitle));
|
|
|
|
SDL_WM_SetCaption(apptitle, NULL);
|
|
|
|
startwin_settitle(apptitle);
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
// ---------------------------------------
|
|
//
|
|
// System
|
|
//
|
|
// ---------------------------------------
|
|
//
|
|
//
|
|
|
|
int32_t main(int32_t argc, char *argv[])
|
|
{
|
|
int32_t r;
|
|
char *argp;
|
|
FILE *fp;
|
|
|
|
#ifdef NEDMALLOC
|
|
nedcreatepool(SYSTEM_POOL_SIZE, -1);
|
|
// atexit(neddestroysyspool);
|
|
#endif
|
|
|
|
buildkeytranslationtable();
|
|
|
|
#ifdef HAVE_GTK2
|
|
gtkbuild_init(&argc, &argv);
|
|
#endif
|
|
startwin_open();
|
|
|
|
_buildargc = argc;
|
|
_buildargv = (const char **)argv;
|
|
|
|
#if !(defined __APPLE__ && defined __BIG_ENDIAN__)
|
|
// pipe standard outputs to files
|
|
if ((argp = Bgetenv("BUILD_LOGSTDOUT")) != NULL)
|
|
if (!Bstrcasecmp(argp, "TRUE"))
|
|
{
|
|
fp = freopen("stdout.txt", "w", stdout);
|
|
|
|
if (!fp)
|
|
fp = fopen("stdout.txt", "w");
|
|
|
|
if (fp)
|
|
{
|
|
setvbuf(fp, 0, _IONBF, 0);
|
|
*stdout = *fp;
|
|
*stderr = *fp;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef USE_OPENGL
|
|
if ((argp = Bgetenv("BUILD_NOFOG")) != NULL)
|
|
nofog = Batol(argp);
|
|
#endif
|
|
|
|
baselayer_init();
|
|
r = app_main(_buildargc, _buildargv);
|
|
|
|
startwin_close();
|
|
#ifdef HAVE_GTK2
|
|
gtkbuild_exit(r);
|
|
#endif
|
|
return r;
|
|
}
|
|
|
|
#ifdef USE_OPENGL
|
|
void setvsync(int32_t sync)
|
|
{
|
|
if (vsync == sync) return;
|
|
vsync = sync;
|
|
resetvideomode();
|
|
if (setgamemode(fullscreen,xdim,ydim,bpp))
|
|
OSD_Printf("restartvid: Reset failed...\n");
|
|
}
|
|
#endif
|
|
|
|
static void attach_debugger_here(void) {}
|
|
|
|
/* XXX: libexecinfo could be used on systems without gnu libc. */
|
|
#if defined __GNUC__ && !defined __OpenBSD__ && !(defined __APPLE__ && defined __BIG_ENDIAN__) && !defined(GEKKO)
|
|
# define PRINTSTACKONSEGV 1
|
|
# include <execinfo.h>
|
|
#endif
|
|
|
|
static void sighandler(int signum)
|
|
{
|
|
UNREFERENCED_PARAMETER(signum);
|
|
// if (signum==SIGSEGV)
|
|
{
|
|
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
|
SDL_ShowCursor(SDL_ENABLE);
|
|
#if PRINTSTACKONSEGV
|
|
{
|
|
void *addr[32];
|
|
int32_t errfd = fileno(stderr);
|
|
int32_t n=backtrace(addr, sizeof(addr)/sizeof(addr[0]));
|
|
backtrace_symbols_fd(addr, n, errfd);
|
|
}
|
|
// This is useful for attaching the debugger post-mortem. For those pesky
|
|
// cases where the program runs through happily when inspected from the start.
|
|
// usleep(15000000);
|
|
#endif
|
|
attach_debugger_here();
|
|
uninitsystem();
|
|
exit(8);
|
|
}
|
|
}
|
|
|
|
//
|
|
// initsystem() -- init SDL systems
|
|
//
|
|
int32_t initsystem(void)
|
|
{
|
|
/*
|
|
#ifdef DEBUGGINGAIDS
|
|
const SDL_VideoInfo *vid;
|
|
#endif
|
|
*/
|
|
const SDL_version *linked = SDL_Linked_Version();
|
|
SDL_version compiled;
|
|
char drvname[32];
|
|
|
|
SDL_VERSION(&compiled);
|
|
|
|
mutex_init(&m_initprintf);
|
|
|
|
initprintf("Initializing SDL system interface "
|
|
"(compiled against SDL version %d.%d.%d, found version %d.%d.%d)\n",
|
|
compiled.major, compiled.minor, compiled.patch,
|
|
linked->major, linked->minor, linked->patch);
|
|
|
|
if (SDL_VERSIONNUM(linked->major,linked->minor,linked->patch) < SDL_REQUIREDVERSION)
|
|
{
|
|
/*reject running under SDL versions older than what is stated in sdl_inc.h */
|
|
initprintf("You need at least v%d.%d.%d of SDL to run this game\n",SDL_MIN_X,SDL_MIN_Y,SDL_MIN_Z);
|
|
return -1;
|
|
}
|
|
|
|
if (SDL_Init(SDL_INIT_VIDEO //| SDL_INIT_TIMER
|
|
#ifdef NOSDLPARACHUTE
|
|
| SDL_INIT_NOPARACHUTE
|
|
#endif
|
|
))
|
|
{
|
|
initprintf("Initialization failed! (%s)\nNon-interactive mode enabled\n", SDL_GetError());
|
|
/* if (SDL_Init(0))
|
|
{
|
|
initprintf("Initialization failed! (%s)\n", SDL_GetError());
|
|
return -1;
|
|
}
|
|
else
|
|
*/
|
|
novideo = 1;
|
|
#ifdef USE_OPENGL
|
|
nogl = 1;
|
|
#endif
|
|
}
|
|
|
|
signal(SIGSEGV, sighandler);
|
|
signal(SIGILL, sighandler); /* clang -fcatch-undefined-behavior uses an ill. insn */
|
|
signal(SIGABRT, sighandler);
|
|
signal(SIGFPE, sighandler);
|
|
|
|
atexit(uninitsystem);
|
|
|
|
frameplace = 0;
|
|
lockcount = 0;
|
|
|
|
#ifdef USE_OPENGL
|
|
if (!novideo && loadgldriver(getenv("BUILD_GLDRV")))
|
|
{
|
|
initprintf("Failed loading OpenGL driver. GL modes will be unavailable.\n");
|
|
nogl = 1;
|
|
}
|
|
#endif
|
|
|
|
#ifndef __APPLE__
|
|
|
|
//icon = loadtarga("icon.tga");
|
|
|
|
if (!novideo)
|
|
{
|
|
appicon = loadappicon();
|
|
if (appicon)
|
|
SDL_WM_SetIcon(appicon, 0);
|
|
}
|
|
#endif
|
|
|
|
if (!novideo)
|
|
if (SDL_VideoDriverName(drvname, 32))
|
|
initprintf("Using \"%s\" video driver\n", drvname);
|
|
|
|
/*
|
|
// dump a quick summary of the graphics hardware
|
|
#ifdef DEBUGGINGAIDS
|
|
vid = SDL_GetVideoInfo();
|
|
initprintf("Video device information:\n");
|
|
initprintf(" Can create hardware surfaces? %s\n", (vid->hw_available)?"Yes":"No");
|
|
initprintf(" Window manager available? %s\n", (vid->wm_available)?"Yes":"No");
|
|
initprintf(" Accelerated hardware blits? %s\n", (vid->blit_hw)?"Yes":"No");
|
|
initprintf(" Accelerated hardware colourkey blits? %s\n", (vid->blit_hw_CC)?"Yes":"No");
|
|
initprintf(" Accelerated hardware alpha blits? %s\n", (vid->blit_hw_A)?"Yes":"No");
|
|
initprintf(" Accelerated software blits? %s\n", (vid->blit_sw)?"Yes":"No");
|
|
initprintf(" Accelerated software colourkey blits? %s\n", (vid->blit_sw_CC)?"Yes":"No");
|
|
initprintf(" Accelerated software alpha blits? %s\n", (vid->blit_sw_A)?"Yes":"No");
|
|
initprintf(" Accelerated colour fills? %s\n", (vid->blit_fill)?"Yes":"No");
|
|
initprintf(" Total video memory: %dKB\n", vid->video_mem);
|
|
#endif
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
|
|
//
|
|
// uninitsystem() -- uninit SDL systems
|
|
//
|
|
void uninitsystem(void)
|
|
{
|
|
uninitinput();
|
|
uninittimer();
|
|
|
|
if (appicon)
|
|
{
|
|
SDL_FreeSurface(appicon);
|
|
appicon = NULL;
|
|
}
|
|
|
|
SDL_Quit();
|
|
|
|
#ifdef USE_OPENGL
|
|
unloadgldriver();
|
|
#endif
|
|
}
|
|
|
|
|
|
//
|
|
// initprintf() -- prints a string to the intitialization window
|
|
//
|
|
void initprintf(const char *f, ...)
|
|
{
|
|
va_list va;
|
|
char buf[2048];
|
|
static char dabuf[2048];
|
|
|
|
va_start(va, f);
|
|
Bvsnprintf(buf, sizeof(buf), f, va);
|
|
va_end(va);
|
|
|
|
OSD_Printf("%s", buf);
|
|
// Bprintf("%s", buf);
|
|
|
|
mutex_lock(&m_initprintf);
|
|
if (Bstrlen(dabuf) + Bstrlen(buf) > 1022)
|
|
{
|
|
startwin_puts(dabuf);
|
|
Bmemset(dabuf, 0, sizeof(dabuf));
|
|
}
|
|
|
|
Bstrcat(dabuf,buf);
|
|
|
|
if (flushlogwindow || Bstrlen(dabuf) > 768)
|
|
{
|
|
startwin_puts(dabuf);
|
|
startwin_idle(NULL);
|
|
Bmemset(dabuf, 0, sizeof(dabuf));
|
|
}
|
|
mutex_unlock(&m_initprintf);
|
|
}
|
|
|
|
//
|
|
// debugprintf() -- prints a debug string to stderr
|
|
//
|
|
void debugprintf(const char *f, ...)
|
|
{
|
|
#if defined DEBUGGINGAIDS && !(defined __APPLE__ && defined __BIG_ENDIAN__)
|
|
va_list va;
|
|
|
|
va_start(va,f);
|
|
Bvfprintf(stderr, f, va);
|
|
va_end(va);
|
|
#else
|
|
UNREFERENCED_PARAMETER(f);
|
|
#endif
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
// ---------------------------------------
|
|
//
|
|
// All things Input
|
|
//
|
|
// ---------------------------------------
|
|
//
|
|
//
|
|
|
|
// static int32_t joyblast=0;
|
|
static SDL_Joystick *joydev = NULL;
|
|
|
|
//
|
|
// initinput() -- init input system
|
|
//
|
|
int32_t initinput(void)
|
|
{
|
|
int32_t i,j;
|
|
|
|
#ifdef __APPLE__
|
|
// force OS X to operate in >1 button mouse mode so that LMB isn't adulterated
|
|
if (!getenv("SDL_HAS3BUTTONMOUSE")) putenv("SDL_HAS3BUTTONMOUSE=1");
|
|
#endif
|
|
if (!remapinit)
|
|
for (i=0; i<256; i++)
|
|
remap[i]=i;
|
|
remapinit=1;
|
|
|
|
if (SDL_EnableKeyRepeat(250, 30)) // doesn't do anything in 1.3
|
|
initprintf("Error enabling keyboard repeat.\n");
|
|
inputdevices = 1|2; // keyboard (1) and mouse (2)
|
|
mousegrab = 0;
|
|
|
|
SDL_EnableUNICODE(1); // let's hope this doesn't hit us too hard
|
|
|
|
memset(key_names,0,sizeof(key_names));
|
|
#if (SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION < 3)
|
|
for (i=0; i<SDLK_LAST; i++)
|
|
{
|
|
if (!keytranslation[i]) continue;
|
|
Bstrncpyz(key_names[ keytranslation[i] ], SDL_GetKeyName(i), sizeof(key_names[i]));
|
|
}
|
|
#else
|
|
for (i=0; i<SDL_NUM_SCANCODES; i++)
|
|
{
|
|
if (!keytranslation[i]) continue;
|
|
Bstrncpyz(key_names[ keytranslation[i] ], SDL_GetKeyName(SDL_SCANCODE_TO_KEYCODE(i)), sizeof(key_names[i]));
|
|
}
|
|
#endif
|
|
|
|
if (!SDL_InitSubSystem(SDL_INIT_JOYSTICK))
|
|
{
|
|
i = SDL_NumJoysticks();
|
|
initprintf("%d joystick(s) found\n",i);
|
|
for (j=0; j<i; j++) initprintf(" %d. %s\n", j+1, SDL_JoystickName(j));
|
|
joydev = SDL_JoystickOpen(0);
|
|
if (joydev)
|
|
{
|
|
SDL_JoystickEventState(SDL_ENABLE);
|
|
inputdevices |= 4;
|
|
|
|
joynumaxes = SDL_JoystickNumAxes(joydev);
|
|
joynumbuttons = min(32,SDL_JoystickNumButtons(joydev));
|
|
joynumhats = SDL_JoystickNumHats(joydev);
|
|
initprintf("Joystick 1 has %d axes, %d buttons, and %d hat(s).\n",
|
|
joynumaxes,joynumbuttons,joynumhats);
|
|
|
|
joyaxis = (int32_t *)Bcalloc(joynumaxes, sizeof(int32_t));
|
|
if (joynumhats)
|
|
joyhat = (int32_t *)Bcalloc(joynumhats, sizeof(int32_t));
|
|
|
|
for (i = 0; i < joynumhats; i++)
|
|
joyhat[i] = -1; // centre
|
|
|
|
joydead = (uint16_t *)Bcalloc(joynumaxes, sizeof(uint16_t));
|
|
joysatur = (uint16_t *)Bcalloc(joynumaxes, sizeof(uint16_t));
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// uninitinput() -- uninit input system
|
|
//
|
|
void uninitinput(void)
|
|
{
|
|
uninitmouse();
|
|
|
|
if (joydev)
|
|
{
|
|
SDL_JoystickClose(joydev);
|
|
joydev = NULL;
|
|
}
|
|
}
|
|
|
|
#ifndef GEKKO
|
|
const char *getjoyname(int32_t what, int32_t num)
|
|
{
|
|
static char tmp[64];
|
|
|
|
switch (what)
|
|
{
|
|
case 0: // axis
|
|
if ((unsigned)num > (unsigned)joynumaxes) return NULL;
|
|
Bsprintf(tmp,"Axis %d",num);
|
|
return (char *)tmp;
|
|
|
|
case 1: // button
|
|
if ((unsigned)num > (unsigned)joynumbuttons) return NULL;
|
|
Bsprintf(tmp,"Button %d",num);
|
|
return (char *)tmp;
|
|
|
|
case 2: // hat
|
|
if ((unsigned)num > (unsigned)joynumhats) return NULL;
|
|
Bsprintf(tmp,"Hat %d",num);
|
|
return (char *)tmp;
|
|
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
#else
|
|
static const char *joynames[3][15] =
|
|
{
|
|
{
|
|
"Left Stick X",
|
|
"Left Stick Y",
|
|
"Right Stick X",
|
|
"Right Stick Y",
|
|
"Axis 5",
|
|
"Axis 6",
|
|
"Axis 7",
|
|
"Axis 8",
|
|
"Axis 9",
|
|
"Axis 10",
|
|
"Axis 11",
|
|
"Axis 12",
|
|
"Axis 13",
|
|
"Axis 14",
|
|
"Axis 15",
|
|
},
|
|
{
|
|
"Button A",
|
|
"Button B",
|
|
"Button 1",
|
|
"Button 2",
|
|
"Button -",
|
|
"Button +",
|
|
"Button HOME",
|
|
"Button Z",
|
|
"Button C",
|
|
"Button X",
|
|
"Button Y",
|
|
"Trigger L",
|
|
"Trigger R",
|
|
"Trigger ZL",
|
|
"Trigger ZR",
|
|
},
|
|
{
|
|
"D-Pad Up",
|
|
"D-Pad Right",
|
|
"D-Pad Down",
|
|
"D-Pad Left",
|
|
"Hat 5",
|
|
"Hat 6",
|
|
"Hat 7",
|
|
"Hat 8",
|
|
"Hat 9",
|
|
"Hat 10",
|
|
"Hat 11",
|
|
"Hat 12",
|
|
"Hat 13",
|
|
"Hat 14",
|
|
"Hat 15",
|
|
}
|
|
};
|
|
const char *getjoyname(int32_t what, int32_t num)
|
|
{
|
|
switch (what)
|
|
{
|
|
case 0: // axis
|
|
if ((unsigned)num > (unsigned)joynumaxes) return NULL;
|
|
return joynames[0][num];
|
|
|
|
case 1: // button
|
|
if ((unsigned)num > (unsigned)joynumbuttons) return NULL;
|
|
return joynames[1][num];
|
|
|
|
case 2: // hat
|
|
if ((unsigned)num > (unsigned)joynumhats) return NULL;
|
|
return joynames[2][num];
|
|
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
//
|
|
// initmouse() -- init mouse input
|
|
//
|
|
int32_t initmouse(void)
|
|
{
|
|
moustat=1;
|
|
grabmouse(1); // FIXME - SA
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// uninitmouse() -- uninit mouse input
|
|
//
|
|
void uninitmouse(void)
|
|
{
|
|
grabmouse(0);
|
|
moustat=0;
|
|
}
|
|
|
|
|
|
//
|
|
// grabmouse() -- show/hide mouse cursor
|
|
//
|
|
void grabmouse(char a)
|
|
{
|
|
if (appactive && moustat)
|
|
{
|
|
if (a != mousegrab)
|
|
{
|
|
#if !defined DEBUGGINGAIDS || defined __APPLE__
|
|
SDL_GrabMode g;
|
|
|
|
g = SDL_WM_GrabInput(a ? SDL_GRAB_ON : SDL_GRAB_OFF);
|
|
mousegrab = (g == SDL_GRAB_ON);
|
|
|
|
SDL_ShowCursor(mousegrab ? SDL_DISABLE : SDL_ENABLE);
|
|
#else
|
|
mousegrab = a;
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mousegrab = a;
|
|
}
|
|
mousex = mousey = 0;
|
|
mouseabsx = mouseabsy = 0;
|
|
}
|
|
|
|
//
|
|
// setjoydeadzone() -- sets the dead and saturation zones for the joystick
|
|
//
|
|
void setjoydeadzone(int32_t axis, uint16_t dead, uint16_t satur)
|
|
{
|
|
joydead[axis] = dead;
|
|
joysatur[axis] = satur;
|
|
}
|
|
|
|
|
|
//
|
|
// getjoydeadzone() -- gets the dead and saturation zones for the joystick
|
|
//
|
|
void getjoydeadzone(int32_t axis, uint16_t *dead, uint16_t *satur)
|
|
{
|
|
*dead = joydead[axis];
|
|
*satur = joysatur[axis];
|
|
}
|
|
|
|
|
|
//
|
|
// releaseallbuttons()
|
|
//
|
|
void releaseallbuttons(void)
|
|
{}
|
|
|
|
|
|
//
|
|
//
|
|
// ---------------------------------------
|
|
//
|
|
// All things Timer
|
|
// Ken did this
|
|
//
|
|
// ---------------------------------------
|
|
//
|
|
//
|
|
|
|
static Uint32 timerfreq=0;
|
|
static Uint32 timerlastsample=0;
|
|
int32_t timerticspersec=0;
|
|
static void(*usertimercallback)(void) = NULL;
|
|
|
|
//
|
|
// inittimer() -- initialize timer
|
|
//
|
|
int32_t inittimer(int32_t tickspersecond)
|
|
{
|
|
if (timerfreq) return 0; // already installed
|
|
|
|
// initprintf("Initializing timer\n");
|
|
|
|
timerfreq = 1000;
|
|
timerticspersec = tickspersecond;
|
|
timerlastsample = SDL_GetTicks() * timerticspersec / timerfreq;
|
|
|
|
usertimercallback = NULL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// uninittimer() -- shut down timer
|
|
//
|
|
void uninittimer(void)
|
|
{
|
|
if (!timerfreq) return;
|
|
|
|
timerfreq=0;
|
|
}
|
|
|
|
//
|
|
// sampletimer() -- update totalclock
|
|
//
|
|
void sampletimer(void)
|
|
{
|
|
Uint32 i;
|
|
int32_t n;
|
|
|
|
if (!timerfreq) return;
|
|
|
|
i = SDL_GetTicks();
|
|
n = (int32_t)(i * timerticspersec / timerfreq) - timerlastsample;
|
|
if (n>0)
|
|
{
|
|
totalclock += n;
|
|
timerlastsample += n;
|
|
}
|
|
|
|
if (usertimercallback) for (; n>0; n--) usertimercallback();
|
|
}
|
|
|
|
//
|
|
// getticks() -- returns the sdl ticks count
|
|
//
|
|
uint32_t getticks(void)
|
|
{
|
|
return (uint32_t)SDL_GetTicks();
|
|
}
|
|
|
|
// high-resolution timers for profiling
|
|
#if (SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION < 3) // SDL 1.2
|
|
uint64_t gethiticks(void)
|
|
{
|
|
return SDL_GetTicks();
|
|
}
|
|
|
|
uint64_t gethitickspersec(void)
|
|
{
|
|
return 1000;
|
|
}
|
|
#else // SDL 1.3
|
|
uint64_t gethiticks(void)
|
|
{
|
|
return SDL_GetPerformanceCounter();
|
|
}
|
|
|
|
uint64_t gethitickspersec(void)
|
|
{
|
|
return SDL_GetPerformanceFrequency();
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// gettimerfreq() -- returns the number of ticks per second the timer is configured to generate
|
|
//
|
|
int32_t gettimerfreq(void)
|
|
{
|
|
return timerticspersec;
|
|
}
|
|
|
|
|
|
//
|
|
// installusertimercallback() -- set up a callback function to be called when the timer is fired
|
|
//
|
|
void(*installusertimercallback(void(*callback)(void)))(void)
|
|
{
|
|
void(*oldtimercallback)(void);
|
|
|
|
oldtimercallback = usertimercallback;
|
|
usertimercallback = callback;
|
|
|
|
return oldtimercallback;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
//
|
|
// ---------------------------------------
|
|
//
|
|
// All things Video
|
|
//
|
|
// ---------------------------------------
|
|
//
|
|
//
|
|
|
|
|
|
//
|
|
// getvalidmodes() -- figure out what video modes are available
|
|
//
|
|
static int32_t sortmodes(const struct validmode_t *a, const struct validmode_t *b)
|
|
{
|
|
int32_t x;
|
|
|
|
if ((x = a->fs - b->fs) != 0) return x;
|
|
if ((x = a->bpp - b->bpp) != 0) return x;
|
|
if ((x = a->xdim - b->xdim) != 0) return x;
|
|
if ((x = a->ydim - b->ydim) != 0) return x;
|
|
|
|
return 0;
|
|
}
|
|
static char modeschecked=0;
|
|
void getvalidmodes(void)
|
|
{
|
|
static int32_t cdepths[] =
|
|
{
|
|
8,
|
|
#ifdef USE_OPENGL
|
|
16,24,32,
|
|
#endif
|
|
0
|
|
};
|
|
SDL_Rect **modes;
|
|
SDL_PixelFormat pf;
|
|
|
|
pf.palette = NULL;
|
|
pf.BitsPerPixel = 8;
|
|
pf.BytesPerPixel = 1;
|
|
|
|
int32_t i, j, maxx=0, maxy=0;
|
|
|
|
if (modeschecked || novideo) return;
|
|
|
|
validmodecnt=0;
|
|
// initprintf("Detecting video modes:\n");
|
|
|
|
#define ADDMODE(x,y,c,f) do { \
|
|
if (validmodecnt<MAXVALIDMODES) { \
|
|
int32_t mn; \
|
|
for(mn=0;mn<validmodecnt;mn++) \
|
|
if (validmode[mn].xdim==x && validmode[mn].ydim==y && \
|
|
validmode[mn].bpp==c && validmode[mn].fs==f) break; \
|
|
if (mn==validmodecnt) { \
|
|
validmode[validmodecnt].xdim=x; \
|
|
validmode[validmodecnt].ydim=y; \
|
|
validmode[validmodecnt].bpp=c; \
|
|
validmode[validmodecnt].fs=f; \
|
|
validmodecnt++; \
|
|
/*initprintf(" - %dx%d %d-bit %s\n", x, y, c, (f&1)?"fullscreen":"windowed");*/ \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
|
|
#define CHECK(w,h) if ((w < maxx) && (h < maxy))
|
|
|
|
// do fullscreen modes first
|
|
for (j=0; cdepths[j]; j++)
|
|
{
|
|
#ifdef USE_OPENGL
|
|
if (nogl && cdepths[j] > 8) continue;
|
|
#endif
|
|
pf.BitsPerPixel = cdepths[j];
|
|
pf.BytesPerPixel = cdepths[j] >> 3;
|
|
|
|
modes = SDL_ListModes(&pf, SURFACE_FLAGS
|
|
// #if (SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION < 3)
|
|
| SDL_FULLSCREEN // not implemented/working in SDL 1.3 SDL_compat.c
|
|
//#endif
|
|
);
|
|
|
|
if (modes == (SDL_Rect **)0)
|
|
{
|
|
if (cdepths[j] > 8) cdepths[j] = -1;
|
|
continue;
|
|
}
|
|
|
|
if (modes == (SDL_Rect **)-1)
|
|
{
|
|
for (i=0; defaultres[i][0]; i++)
|
|
ADDMODE(defaultres[i][0],defaultres[i][1],cdepths[j],1);
|
|
}
|
|
else
|
|
{
|
|
for (i=0; modes[i]; i++)
|
|
{
|
|
if ((modes[i]->w > MAXXDIM) || (modes[i]->h > MAXYDIM)) continue;
|
|
|
|
ADDMODE(modes[i]->w, modes[i]->h, cdepths[j], 1);
|
|
|
|
if ((modes[i]->w > maxx) && (modes[i]->h > maxy))
|
|
{
|
|
maxx = modes[i]->w;
|
|
maxy = modes[i]->h;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (maxx == 0 && maxy == 0)
|
|
{
|
|
initprintf("No fullscreen modes available!\n");
|
|
maxx = MAXXDIM; maxy = MAXYDIM;
|
|
}
|
|
|
|
// add windowed modes next
|
|
for (j=0; cdepths[j]; j++)
|
|
{
|
|
#ifdef USE_OPENGL
|
|
if (nogl && cdepths[j] > 8) continue;
|
|
#endif
|
|
if (cdepths[j] < 0) continue;
|
|
for (i=0; defaultres[i][0]; i++)
|
|
CHECK(defaultres[i][0],defaultres[i][1])
|
|
ADDMODE(defaultres[i][0],defaultres[i][1],cdepths[j],0);
|
|
}
|
|
|
|
#undef CHECK
|
|
#undef ADDMODE
|
|
|
|
qsort((void *)validmode, validmodecnt, sizeof(struct validmode_t), (int32_t( *)(const void *,const void *))sortmodes);
|
|
|
|
modeschecked=1;
|
|
}
|
|
|
|
|
|
//
|
|
// checkvideomode() -- makes sure the video mode passed is legal
|
|
//
|
|
int32_t checkvideomode(int32_t *x, int32_t *y, int32_t c, int32_t fs, int32_t forced)
|
|
{
|
|
int32_t i, nearest=-1, dx, dy, odx=9999, ody=9999;
|
|
|
|
getvalidmodes();
|
|
|
|
if (c>8
|
|
#ifdef USE_OPENGL
|
|
&& nogl
|
|
#endif
|
|
) return -1;
|
|
|
|
// fix up the passed resolution values to be multiples of 8
|
|
// and at least 320x200 or at most MAXXDIMxMAXYDIM
|
|
if (*x < 320) *x = 320;
|
|
if (*y < 200) *y = 200;
|
|
if (*x > MAXXDIM) *x = MAXXDIM;
|
|
if (*y > MAXYDIM) *y = MAXYDIM;
|
|
// *x &= 0xfffffff8l;
|
|
|
|
for (i=0; i<validmodecnt; i++)
|
|
{
|
|
if (validmode[i].bpp != c) continue;
|
|
if (validmode[i].fs != fs) continue;
|
|
dx = klabs(validmode[i].xdim - *x);
|
|
dy = klabs(validmode[i].ydim - *y);
|
|
if (!(dx | dy))
|
|
{
|
|
// perfect match
|
|
nearest = i;
|
|
break;
|
|
}
|
|
if ((dx <= odx) && (dy <= ody))
|
|
{
|
|
nearest = i;
|
|
odx = dx; ody = dy;
|
|
}
|
|
}
|
|
|
|
#ifdef ANY_WINDOWED_SIZE
|
|
if (!forced && (fs&1) == 0 && (nearest < 0 || (validmode[nearest].xdim!=*x || validmode[nearest].ydim!=*y)))
|
|
return 0x7fffffffl;
|
|
#endif
|
|
|
|
if (nearest < 0)
|
|
{
|
|
// no mode that will match (eg. if no fullscreen modes)
|
|
return -1;
|
|
}
|
|
|
|
*x = validmode[nearest].xdim;
|
|
*y = validmode[nearest].ydim;
|
|
|
|
return nearest; // JBF 20031206: Returns the mode number
|
|
}
|
|
|
|
|
|
//
|
|
// setvideomode() -- set SDL video mode
|
|
//
|
|
int32_t setvideomode(int32_t x, int32_t y, int32_t c, int32_t fs)
|
|
{
|
|
int32_t regrab = 0;
|
|
#ifdef USE_OPENGL
|
|
static int32_t warnonce = 0;
|
|
# if (SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION < 3)
|
|
static int32_t ovsync = 1;
|
|
# endif
|
|
#endif
|
|
if ((fs == fullscreen) && (x == xres) && (y == yres) && (c == bpp) &&
|
|
!videomodereset)
|
|
{
|
|
OSD_ResizeDisplay(xres,yres);
|
|
return 0;
|
|
}
|
|
|
|
if (checkvideomode(&x,&y,c,fs,0) < 0) return -1;
|
|
|
|
startwin_close();
|
|
|
|
if (mousegrab)
|
|
{
|
|
regrab = 1;
|
|
grabmouse(0);
|
|
}
|
|
|
|
if (lockcount) while (lockcount) enddrawing();
|
|
|
|
#ifdef USE_OPENGL
|
|
if (bpp > 8 && sdl_surface) polymost_glreset();
|
|
#endif
|
|
|
|
// clear last gamma/contrast/brightness so that it will be set anew
|
|
lastvidgcb[0] = lastvidgcb[1] = lastvidgcb[2] = 0.0f;
|
|
|
|
// restore gamma before we change video modes if it was changed
|
|
if (sdl_surface && gammabrightness)
|
|
{
|
|
SDL_SetGammaRamp(sysgamma[0], sysgamma[1], sysgamma[2]);
|
|
gammabrightness = 0; // redetect on next mode switch
|
|
}
|
|
|
|
#ifdef USE_OPENGL
|
|
if (c > 8)
|
|
{
|
|
int32_t i, j, multisamplecheck = (glmultisample > 0);
|
|
struct
|
|
{
|
|
SDL_GLattr attr;
|
|
int32_t value;
|
|
}
|
|
attributes[] =
|
|
{
|
|
# if 0
|
|
{ SDL_GL_RED_SIZE, 8 },
|
|
{ SDL_GL_GREEN_SIZE, 8 },
|
|
{ SDL_GL_BLUE_SIZE, 8 },
|
|
{ SDL_GL_ALPHA_SIZE, 8 },
|
|
{ SDL_GL_BUFFER_SIZE, c },
|
|
{ SDL_GL_STENCIL_SIZE, 0 },
|
|
{ SDL_GL_ACCUM_RED_SIZE, 0 },
|
|
{ SDL_GL_ACCUM_GREEN_SIZE, 0 },
|
|
{ SDL_GL_ACCUM_BLUE_SIZE, 0 },
|
|
{ SDL_GL_ACCUM_ALPHA_SIZE, 0 },
|
|
{ SDL_GL_DEPTH_SIZE, 24 },
|
|
# endif
|
|
{ SDL_GL_DOUBLEBUFFER, 1 },
|
|
{ SDL_GL_MULTISAMPLEBUFFERS, glmultisample > 0 },
|
|
{ SDL_GL_MULTISAMPLESAMPLES, glmultisample },
|
|
{ SDL_GL_STENCIL_SIZE, 1 },
|
|
# if (SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION < 3)
|
|
{ SDL_GL_SWAP_CONTROL, vsync },
|
|
# endif
|
|
};
|
|
|
|
if (nogl) return -1;
|
|
|
|
initprintf("Setting video mode %dx%d (%d-bpp %s)\n",
|
|
x,y,c, ((fs&1) ? "fullscreen" : "windowed"));
|
|
do
|
|
{
|
|
for (i=0; i < (int32_t)(sizeof(attributes)/sizeof(attributes[0])); i++)
|
|
{
|
|
j = attributes[i].value;
|
|
if (!multisamplecheck &&
|
|
(attributes[i].attr == SDL_GL_MULTISAMPLEBUFFERS ||
|
|
attributes[i].attr == SDL_GL_MULTISAMPLESAMPLES)
|
|
)
|
|
{
|
|
j = 0;
|
|
}
|
|
SDL_GL_SetAttribute(attributes[i].attr, j);
|
|
}
|
|
|
|
/* HACK: changing SDL GL attribs only works before surface creation,
|
|
so we have to create a new surface in a different format first
|
|
to force the surface we WANT to be recreated instead of reused. */
|
|
# if (SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION < 3)
|
|
if (vsync != ovsync)
|
|
{
|
|
if (sdl_surface)
|
|
{
|
|
SDL_FreeSurface(sdl_surface);
|
|
sdl_surface = SDL_SetVideoMode(1, 1, 8, SDL_NOFRAME | SURFACE_FLAGS | ((fs&1)?SDL_FULLSCREEN:0));
|
|
SDL_FreeSurface(sdl_surface);
|
|
}
|
|
ovsync = vsync;
|
|
}
|
|
# endif
|
|
sdl_surface = SDL_SetVideoMode(x, y, c, SDL_OPENGL | ((fs&1)?SDL_FULLSCREEN:0));
|
|
if (!sdl_surface)
|
|
{
|
|
if (multisamplecheck)
|
|
{
|
|
initprintf("Multisample mode not possible. Retrying without multisampling.\n");
|
|
glmultisample = 0;
|
|
continue;
|
|
}
|
|
initprintf("Unable to set video mode!\n");
|
|
return -1;
|
|
}
|
|
}
|
|
while (multisamplecheck--);
|
|
}
|
|
else
|
|
#endif // defined USE_OPENGL
|
|
{
|
|
initprintf("Setting video mode %dx%d (%d-bpp %s)\n",
|
|
x,y,c, ((fs&1) ? "fullscreen" : "windowed"));
|
|
sdl_surface = SDL_SetVideoMode(x, y, c, SURFACE_FLAGS | ((fs&1)?SDL_FULLSCREEN:0));
|
|
if (!sdl_surface)
|
|
{
|
|
initprintf("Unable to set video mode!\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
{
|
|
char flags[512] = "";
|
|
# define FLAG(x,y) if ((sdl_surface->flags & x) == x) { strcat(flags, y); strcat(flags, " "); }
|
|
FLAG(SDL_HWSURFACE, "HWSURFACE") else
|
|
FLAG(SDL_SWSURFACE, "SWSURFACE")
|
|
FLAG(SDL_ASYNCBLIT, "ASYNCBLIT")
|
|
FLAG(SDL_ANYFORMAT, "ANYFORMAT")
|
|
FLAG(SDL_HWPALETTE, "HWPALETTE")
|
|
FLAG(SDL_DOUBLEBUF, "DOUBLEBUF")
|
|
FLAG(SDL_FULLSCREEN, "FULLSCREEN")
|
|
FLAG(SDL_OPENGL, "OPENGL")
|
|
FLAG(SDL_OPENGLBLIT, "OPENGLBLIT")
|
|
FLAG(SDL_RESIZABLE, "RESIZABLE")
|
|
FLAG(SDL_HWACCEL, "HWACCEL")
|
|
FLAG(SDL_SRCCOLORKEY, "SRCCOLORKEY")
|
|
FLAG(SDL_RLEACCEL, "RLEACCEL")
|
|
FLAG(SDL_SRCALPHA, "SRCALPHA")
|
|
FLAG(SDL_PREALLOC, "PREALLOC")
|
|
# undef FLAG
|
|
initprintf("SDL Surface flags: %s\n", flags);
|
|
}
|
|
#endif
|
|
|
|
{
|
|
//static char t[384];
|
|
//sprintf(t, "%s (%dx%d %s)", apptitle, x, y, ((fs) ? "fullscreen" : "windowed"));
|
|
SDL_WM_SetCaption(apptitle, 0);
|
|
}
|
|
|
|
#ifdef USE_OPENGL
|
|
if (c > 8)
|
|
{
|
|
char *p,*p2,*p3;
|
|
|
|
polymost_glreset();
|
|
|
|
bglEnable(GL_TEXTURE_2D);
|
|
bglShadeModel(GL_SMOOTH); //GL_FLAT
|
|
bglClearColor(0,0,0,0.5); //Black Background
|
|
bglHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST); //Use FASTEST for ortho!
|
|
bglHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
|
|
bglDisable(GL_DITHER);
|
|
|
|
glinfo.vendor = (const char *)bglGetString(GL_VENDOR);
|
|
glinfo.renderer = (const char *)bglGetString(GL_RENDERER);
|
|
glinfo.version = (const char *)bglGetString(GL_VERSION);
|
|
glinfo.extensions = (const char *)bglGetString(GL_EXTENSIONS);
|
|
|
|
# ifdef POLYMER
|
|
if (!Bstrcmp(glinfo.vendor,"ATI Technologies Inc."))
|
|
{
|
|
pr_ati_fboworkaround = 1;
|
|
initprintf("Enabling ATI FBO color attachment workaround.\n");
|
|
|
|
if (Bstrstr(glinfo.renderer,"Radeon X1"))
|
|
{
|
|
pr_ati_nodepthoffset = 1;
|
|
initprintf("Enabling ATI R520 polygon offset workaround.\n");
|
|
}
|
|
else
|
|
pr_ati_nodepthoffset = 0;
|
|
# ifdef __APPLE__
|
|
//See bug description at http://lists.apple.com/archives/mac-opengl/2005/Oct/msg00169.html
|
|
if (!Bstrncmp(glinfo.renderer,"ATI Radeon 9600", 15))
|
|
{
|
|
pr_ati_textureformat_one = 1;
|
|
initprintf("Enabling ATI Radeon 9600 texture format workaround.\n");
|
|
}
|
|
else
|
|
pr_ati_textureformat_one = 0;
|
|
# endif
|
|
}
|
|
else
|
|
pr_ati_fboworkaround = 0;
|
|
# endif // defined POLYMER
|
|
|
|
glinfo.maxanisotropy = 1.0;
|
|
glinfo.bgra = 0;
|
|
glinfo.texcompr = 0;
|
|
|
|
// process the extensions string and flag stuff we recognize
|
|
p = Bstrdup(glinfo.extensions);
|
|
p3 = p;
|
|
while ((p2 = Bstrtoken(p3==p?p:NULL, " ", (char **)&p3, 1)) != NULL)
|
|
{
|
|
if (!Bstrcmp(p2, "GL_EXT_texture_filter_anisotropic"))
|
|
{
|
|
// supports anisotropy. get the maximum anisotropy level
|
|
bglGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glinfo.maxanisotropy);
|
|
}
|
|
else if (!Bstrcmp(p2, "GL_EXT_texture_edge_clamp") ||
|
|
!Bstrcmp(p2, "GL_SGIS_texture_edge_clamp"))
|
|
{
|
|
// supports GL_CLAMP_TO_EDGE or GL_CLAMP_TO_EDGE_SGIS
|
|
glinfo.clamptoedge = 1;
|
|
}
|
|
else if (!Bstrcmp(p2, "GL_EXT_bgra"))
|
|
{
|
|
// support bgra textures
|
|
glinfo.bgra = 1;
|
|
}
|
|
else if (!Bstrcmp(p2, "GL_ARB_texture_compression") && Bstrcmp(glinfo.vendor,"ATI Technologies Inc."))
|
|
{
|
|
// support texture compression
|
|
glinfo.texcompr = 1;
|
|
}
|
|
else if (!Bstrcmp(p2, "GL_ARB_texture_non_power_of_two"))
|
|
{
|
|
// support non-power-of-two texture sizes
|
|
glinfo.texnpot = 1;
|
|
}
|
|
else if (!Bstrcmp(p2, "WGL_3DFX_gamma_control"))
|
|
{
|
|
// 3dfx cards have issues with fog
|
|
nofog = 1;
|
|
if (!(warnonce&1)) initprintf("3dfx card detected: OpenGL fog disabled\n");
|
|
warnonce |= 1;
|
|
}
|
|
else if (!Bstrcmp(p2, "GL_ARB_multisample"))
|
|
{
|
|
// supports multisampling
|
|
glinfo.multisample = 1;
|
|
}
|
|
else if (!Bstrcmp(p2, "GL_NV_multisample_filter_hint"))
|
|
{
|
|
// supports nvidia's multisample hint extension
|
|
glinfo.nvmultisamplehint = 1;
|
|
}
|
|
else if (!Bstrcmp((char *)p2, "GL_ARB_fragment_program"))
|
|
{
|
|
glinfo.arbfp = 1;
|
|
}
|
|
else if (!Bstrcmp((char *)p2, "GL_ARB_depth_texture"))
|
|
{
|
|
glinfo.depthtex = 1;
|
|
}
|
|
else if (!Bstrcmp((char *)p2, "GL_ARB_shadow"))
|
|
{
|
|
glinfo.shadow = 1;
|
|
}
|
|
else if (!Bstrcmp((char *)p2, "GL_EXT_framebuffer_object"))
|
|
{
|
|
glinfo.fbos = 1;
|
|
}
|
|
else if (!Bstrcmp((char *)p2, "GL_NV_texture_rectangle") ||
|
|
!Bstrcmp((char *)p2, "GL_EXT_texture_rectangle"))
|
|
{
|
|
glinfo.rect = 1;
|
|
}
|
|
else if (!Bstrcmp((char *)p2, "GL_ARB_multitexture"))
|
|
{
|
|
glinfo.multitex = 1;
|
|
}
|
|
else if (!Bstrcmp((char *)p2, "GL_ARB_texture_env_combine"))
|
|
{
|
|
glinfo.envcombine = 1;
|
|
}
|
|
else if (!Bstrcmp((char *)p2, "GL_ARB_vertex_buffer_object"))
|
|
{
|
|
glinfo.vbos = 1;
|
|
}
|
|
else if (!Bstrcmp((char *)p2, "GL_EXT_gpu_shader4"))
|
|
{
|
|
glinfo.sm4 = 1;
|
|
}
|
|
else if (!Bstrcmp((char *)p2, "GL_ARB_occlusion_query"))
|
|
{
|
|
glinfo.occlusionqueries = 1;
|
|
}
|
|
else if (!Bstrcmp((char *)p2, "GL_ARB_shader_objects"))
|
|
{
|
|
glinfo.glsl = 1;
|
|
}
|
|
else if (!Bstrcmp((char *)p2, "GL_ARB_debug_output"))
|
|
{
|
|
glinfo.debugoutput = 1;
|
|
}
|
|
}
|
|
Bfree(p);
|
|
|
|
if (!glinfo.dumped)
|
|
{
|
|
int32_t oldbpp = bpp;
|
|
bpp = 32;
|
|
osdcmd_glinfo(NULL);
|
|
glinfo.dumped = 1;
|
|
bpp = oldbpp;
|
|
}
|
|
}
|
|
#endif // defined USE_OPENGL
|
|
|
|
xres = x;
|
|
yres = y;
|
|
bpp = c;
|
|
fullscreen = fs;
|
|
//bytesperline = sdl_surface->pitch;
|
|
numpages = c>8?2:1;
|
|
frameplace = 0;
|
|
lockcount = 0;
|
|
modechange=1;
|
|
videomodereset = 0;
|
|
OSD_ResizeDisplay(xres,yres);
|
|
|
|
// save the current system gamma to determine if gamma is available
|
|
if (!gammabrightness)
|
|
{
|
|
// float f = 1.0 + ((float)curbrightness / 10.0);
|
|
if (SDL_GetGammaRamp(sysgamma[0], sysgamma[1], sysgamma[2]) >= 0)
|
|
gammabrightness = 1;
|
|
|
|
// see if gamma really is working by trying to set the brightness
|
|
if (gammabrightness && setgamma() < 0)
|
|
gammabrightness = 0; // nope
|
|
}
|
|
|
|
// setpalettefade will set the palette according to whether gamma worked
|
|
setpalettefade(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
|
|
|
|
//if (c==8) setpalette(0,256,0);
|
|
//baselayer_onvideomodechange(c>8);
|
|
|
|
if (regrab) grabmouse(1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//
|
|
// resetvideomode() -- resets the video system
|
|
//
|
|
void resetvideomode(void)
|
|
{
|
|
videomodereset = 1;
|
|
modeschecked = 0;
|
|
}
|
|
|
|
|
|
//
|
|
// begindrawing() -- locks the framebuffer for drawing
|
|
//
|
|
void begindrawing(void)
|
|
{
|
|
int32_t i,j;
|
|
|
|
if (bpp > 8)
|
|
{
|
|
if (offscreenrendering) return;
|
|
frameplace = 0;
|
|
bytesperline = 0;
|
|
modechange = 0;
|
|
return;
|
|
}
|
|
|
|
// lock the frame
|
|
if (lockcount++ > 0)
|
|
return;
|
|
|
|
if (offscreenrendering) return;
|
|
|
|
if (SDL_MUSTLOCK(sdl_surface)) SDL_LockSurface(sdl_surface);
|
|
frameplace = (intptr_t)sdl_surface->pixels;
|
|
|
|
if (sdl_surface->pitch != bytesperline || modechange)
|
|
{
|
|
bytesperline = sdl_surface->pitch;
|
|
setvlinebpl(bytesperline);
|
|
|
|
j = 0;
|
|
for (i=0; i<=ydim; i++) ylookup[i] = j, j += bytesperline;
|
|
modechange=0;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// enddrawing() -- unlocks the framebuffer
|
|
//
|
|
void enddrawing(void)
|
|
{
|
|
if (bpp > 8)
|
|
{
|
|
if (!offscreenrendering) frameplace = 0;
|
|
return;
|
|
}
|
|
|
|
if (!frameplace) return;
|
|
if (lockcount > 1) { lockcount--; return; }
|
|
if (!offscreenrendering) frameplace = 0;
|
|
if (lockcount == 0) return;
|
|
lockcount = 0;
|
|
|
|
if (offscreenrendering) return;
|
|
|
|
if (SDL_MUSTLOCK(sdl_surface)) SDL_UnlockSurface(sdl_surface);
|
|
}
|
|
|
|
static int32_t needpalupdate;
|
|
static SDL_Color sdlayer_pal[256];
|
|
|
|
//
|
|
// showframe() -- update the display
|
|
//
|
|
void showframe(int32_t w)
|
|
{
|
|
// int32_t i,j;
|
|
UNREFERENCED_PARAMETER(w);
|
|
|
|
#ifdef USE_OPENGL
|
|
if (bpp > 8)
|
|
{
|
|
if (palfadedelta)
|
|
{
|
|
bglMatrixMode(GL_PROJECTION);
|
|
bglPushMatrix();
|
|
bglLoadIdentity();
|
|
bglMatrixMode(GL_MODELVIEW);
|
|
bglPushMatrix();
|
|
bglLoadIdentity();
|
|
|
|
bglDisable(GL_DEPTH_TEST);
|
|
bglDisable(GL_ALPHA_TEST);
|
|
bglDisable(GL_TEXTURE_2D);
|
|
|
|
bglEnable(GL_BLEND);
|
|
bglColor4ub(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
|
|
|
|
bglBegin(GL_TRIANGLES);
|
|
bglVertex2f(-2.5f, 1.f);
|
|
bglVertex2f(2.5f, 1.f);
|
|
bglVertex2f(.0f, -2.5f);
|
|
bglEnd();
|
|
|
|
bglDisable(GL_BLEND);
|
|
|
|
bglPopMatrix();
|
|
bglMatrixMode(GL_PROJECTION);
|
|
bglPopMatrix();
|
|
}
|
|
|
|
SDL_GL_SwapBuffers();
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (offscreenrendering) return;
|
|
|
|
if (lockcount)
|
|
{
|
|
printf("Frame still locked %d times when showframe() called.\n", lockcount);
|
|
while (lockcount) enddrawing();
|
|
}
|
|
|
|
// deferred palette updating
|
|
if (needpalupdate)
|
|
{
|
|
SDL_SetColors(sdl_surface, sdlayer_pal, 0, 256);
|
|
// same as:
|
|
//SDL_SetPalette(sdl_surface, SDL_LOGPAL|SDL_PHYSPAL, pal, 0, 256);
|
|
needpalupdate = 0;
|
|
}
|
|
|
|
SDL_Flip(sdl_surface);
|
|
}
|
|
|
|
|
|
//
|
|
// setpalette() -- set palette values
|
|
//
|
|
int32_t setpalette(int32_t start, int32_t num)
|
|
{
|
|
int32_t i,n;
|
|
|
|
if (bpp > 8) return 0; // no palette in opengl
|
|
|
|
Bmemcpy(sdlayer_pal, curpalettefaded, 256*4);
|
|
|
|
for (i=start, n=num; n>0; i++, n--)
|
|
curpalettefaded[i].f = sdlayer_pal[i].unused = 0;
|
|
|
|
needpalupdate = 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// getpalette() -- get palette values
|
|
//
|
|
#if 0
|
|
int32_t getpalette(int32_t start, int32_t num, char *dapal)
|
|
{
|
|
int32_t i;
|
|
SDL_Palette *pal;
|
|
|
|
// we shouldn't need to lock the surface to get the palette
|
|
pal = sdl_surface->format->palette;
|
|
|
|
for (i=num; i>0; i--, start++) {
|
|
dapal[0] = pal->colors[start].b >> 2;
|
|
dapal[1] = pal->colors[start].g >> 2;
|
|
dapal[2] = pal->colors[start].r >> 2;
|
|
dapal += 4;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// setgamma
|
|
//
|
|
int32_t setgamma(void)
|
|
{
|
|
int32_t i;
|
|
uint16_t gammaTable[768];
|
|
float gamma = max(0.1f,min(4.f,vid_gamma));
|
|
float contrast = max(0.1f,min(3.f,vid_contrast));
|
|
float bright = max(-0.8f,min(0.8f,vid_brightness));
|
|
|
|
double invgamma = 1 / gamma;
|
|
double norm = pow(255., invgamma - 1);
|
|
|
|
if (novideo) return 0;
|
|
|
|
if (lastvidgcb[0]==gamma && lastvidgcb[1]==contrast && lastvidgcb[2]==bright)
|
|
return 0;
|
|
|
|
// This formula is taken from Doomsday
|
|
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
double val = i * contrast - (contrast - 1) * 127;
|
|
if (gamma != 1) val = pow(val, invgamma) / norm;
|
|
val += bright * 128;
|
|
|
|
gammaTable[i] = gammaTable[i + 256] = gammaTable[i + 512] = (uint16_t)max(0.f,(double)min(0xffff,val*256));
|
|
}
|
|
|
|
i = SDL_SetGammaRamp(&gammaTable[0],&gammaTable[256],&gammaTable[512]);
|
|
|
|
if (i != -1)
|
|
{
|
|
lastvidgcb[0] = gamma;
|
|
lastvidgcb[1] = contrast;
|
|
lastvidgcb[2] = bright;
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
#ifndef __APPLE__
|
|
extern struct sdlappicon sdlappicon;
|
|
static SDL_Surface *loadappicon(void)
|
|
{
|
|
SDL_Surface *surf;
|
|
|
|
surf = SDL_CreateRGBSurfaceFrom((void *)sdlappicon.pixels,
|
|
sdlappicon.width, sdlappicon.height, 32, sdlappicon.width*4,
|
|
0xffl,0xff00l,0xff0000l,0xff000000l);
|
|
|
|
return surf;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
//
|
|
// ---------------------------------------
|
|
//
|
|
// Miscellany
|
|
//
|
|
// ---------------------------------------
|
|
//
|
|
//
|
|
|
|
|
|
//
|
|
// handleevents() -- process the SDL message queue
|
|
// returns !0 if there was an important event worth checking (like quitting)
|
|
//
|
|
|
|
int32_t handleevents(void)
|
|
{
|
|
int32_t code, rv=0, j;
|
|
SDL_Event ev;
|
|
|
|
while (SDL_PollEvent(&ev))
|
|
{
|
|
switch (ev.type)
|
|
{
|
|
#if (SDL_MAJOR_VERSION > 1 || SDL_MINOR_VERSION > 2)
|
|
case SDL_TEXTINPUT:
|
|
j = 0;
|
|
do
|
|
{
|
|
code = ev.text.text[j];
|
|
|
|
if (code != scantoasc[OSD_OSDKey()] && ((keyasciififoend+1)&(KEYFIFOSIZ-1)) != keyasciififoplc)
|
|
{
|
|
if (OSD_HandleChar(code))
|
|
{
|
|
keyasciififo[keyasciififoend] = code;
|
|
keyasciififoend = ((keyasciififoend+1)&(KEYFIFOSIZ-1));
|
|
}
|
|
}
|
|
}
|
|
while (j < SDL_TEXTINPUTEVENT_TEXT_SIZE && ev.text.text[++j]);
|
|
break;
|
|
|
|
case SDL_KEYDOWN:
|
|
case SDL_KEYUP:
|
|
code = keytranslation[ev.key.keysym.scancode];
|
|
|
|
if (ev.key.type == SDL_KEYDOWN &&
|
|
(ev.key.keysym.scancode == SDL_SCANCODE_RETURN ||
|
|
ev.key.keysym.scancode == SDL_SCANCODE_BACKSPACE ||
|
|
ev.key.keysym.scancode == SDL_SCANCODE_TAB) &&
|
|
((keyasciififoend+1)&(KEYFIFOSIZ-1)) != keyasciififoplc)
|
|
{
|
|
if (OSD_HandleChar(ev.key.keysym.unicode & 0x7f))
|
|
{
|
|
keyasciififo[keyasciififoend] = ev.key.keysym.unicode & 0x7f;
|
|
keyasciififoend = ((keyasciififoend+1)&(KEYFIFOSIZ-1));
|
|
}
|
|
}
|
|
|
|
// printf("got key %d, %d\n",ev.key.keysym.scancode,code);
|
|
|
|
// hook in the osd
|
|
if (OSD_HandleScanCode(code, (ev.key.type == SDL_KEYDOWN)) == 0)
|
|
break;
|
|
|
|
if (ev.key.type == SDL_KEYDOWN)
|
|
{
|
|
if (!keystatus[code])
|
|
{
|
|
SetKey(code, 1);
|
|
if (keypresscallback)
|
|
keypresscallback(code, 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# ifdef __linux
|
|
// The pause key generates a release event right after
|
|
// the pressing one on linux. As a result, it gets unseen
|
|
// by the game most of the time.
|
|
if (code == 0x59) // pause
|
|
break;
|
|
# endif
|
|
SetKey(code, 0);
|
|
if (keypresscallback)
|
|
keypresscallback(code, 0);
|
|
}
|
|
break;
|
|
case SDL_WINDOWEVENT:
|
|
switch (ev.window.event)
|
|
{
|
|
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
|
appactive = 1;
|
|
# ifndef DEBUGGINGAIDS
|
|
if (mousegrab && moustat)
|
|
{
|
|
SDL_WM_GrabInput(SDL_GRAB_ON);
|
|
SDL_ShowCursor(SDL_DISABLE);
|
|
}
|
|
# endif
|
|
break;
|
|
case SDL_WINDOWEVENT_FOCUS_LOST:
|
|
appactive = 0;
|
|
# ifndef DEBUGGINGAIDS
|
|
if (mousegrab && moustat)
|
|
{
|
|
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
|
SDL_ShowCursor(SDL_ENABLE);
|
|
}
|
|
# endif
|
|
break;
|
|
}
|
|
break;
|
|
/*
|
|
case SDL_MOUSEWHEEL:
|
|
initprintf("wheel y %d\n",ev.wheel.y);
|
|
if (ev.wheel.y > 0)
|
|
{
|
|
mwheelup = totalclock;
|
|
mouseb |= 16;
|
|
if (mousepresscallback)
|
|
mousepresscallback(5, 1);
|
|
}
|
|
if (ev.wheel.y < 0)
|
|
{
|
|
mwheeldown = totalclock;
|
|
mouseb |= 32;
|
|
if (mousepresscallback)
|
|
mousepresscallback(6, 1);
|
|
}
|
|
break;
|
|
*/
|
|
// #warning "Using SDL 1.3"
|
|
#else // SDL 1.3 ^^^ | vvv SDL 1.2
|
|
// #warning "Using SDL 1.2"
|
|
case SDL_KEYDOWN:
|
|
case SDL_KEYUP:
|
|
code = keytranslation[ev.key.keysym.sym];
|
|
# ifdef KEY_PRINT_DEBUG
|
|
printf("keytranslation[%d] = %s (%d) %s\n", ev.key.keysym.sym,
|
|
key_names[code], code, ev.key.type==SDL_KEYDOWN?"DOWN":"UP");
|
|
# endif
|
|
if (code != OSD_OSDKey() && ev.key.keysym.unicode != 0 && ev.key.type == SDL_KEYDOWN &&
|
|
(ev.key.keysym.unicode & 0xff80) == 0 &&
|
|
((keyasciififoend+1)&(KEYFIFOSIZ-1)) != keyasciififoplc)
|
|
{
|
|
if (OSD_HandleChar(ev.key.keysym.unicode & 0x7f))
|
|
{
|
|
keyasciififo[keyasciififoend] = ev.key.keysym.unicode & 0x7f;
|
|
keyasciififoend = ((keyasciififoend+1)&(KEYFIFOSIZ-1));
|
|
}
|
|
}
|
|
|
|
// hook in the osd
|
|
// if (ev.type==SDL_KEYDOWN)
|
|
// printf("got key SDLK %d (%s), trans 0x%x\n", ev.key.keysym.sym, SDL_GetKeyName(ev.key.keysym.sym), code);
|
|
if (OSD_HandleScanCode(code, (ev.key.type == SDL_KEYDOWN)) == 0)
|
|
break;
|
|
|
|
if (ev.key.type == SDL_KEYDOWN)
|
|
{
|
|
if (!keystatus[code])
|
|
{
|
|
SetKey(code, 1);
|
|
if (keypresscallback)
|
|
keypresscallback(code, 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# ifdef __linux
|
|
if (code == 0x59) // pause
|
|
break;
|
|
# endif
|
|
SetKey(code, 0);
|
|
if (keypresscallback)
|
|
keypresscallback(code, 0);
|
|
}
|
|
break;
|
|
|
|
case SDL_ACTIVEEVENT:
|
|
if (ev.active.state & SDL_APPINPUTFOCUS)
|
|
{
|
|
appactive = ev.active.gain;
|
|
# ifndef DEBUGGINGAIDS
|
|
if (mousegrab && moustat)
|
|
{
|
|
if (appactive)
|
|
{
|
|
SDL_WM_GrabInput(SDL_GRAB_ON);
|
|
SDL_ShowCursor(SDL_DISABLE);
|
|
}
|
|
else
|
|
{
|
|
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
|
SDL_ShowCursor(SDL_ENABLE);
|
|
}
|
|
}
|
|
# endif
|
|
rv=-1;
|
|
}
|
|
break;
|
|
#endif // SDL version
|
|
|
|
case SDL_MOUSEBUTTONDOWN:
|
|
case SDL_MOUSEBUTTONUP:
|
|
//if (ev.button.button>=0)
|
|
// initprintf("BTN %d\n", ev.button.button);
|
|
switch (ev.button.button)
|
|
{
|
|
// some of these get reordered to match winlayer
|
|
default:
|
|
j = -1; break;
|
|
case SDL_BUTTON_LEFT:
|
|
j = 0; break;
|
|
case SDL_BUTTON_RIGHT:
|
|
j = 1; break;
|
|
case SDL_BUTTON_MIDDLE:
|
|
j = 2; break;
|
|
case 8 /*SDL_BUTTON_X1*/: // 8 --> 3
|
|
j = 3; break;
|
|
case SDL_BUTTON_WHEELUP: // 4
|
|
case SDL_BUTTON_WHEELDOWN: // 5
|
|
j = ev.button.button; break;
|
|
case 9 /*SDL_BUTTON_X2*/: // 9 --> 6
|
|
j = 6; break;
|
|
}
|
|
if (j<0) break;
|
|
|
|
if (ev.button.state == SDL_PRESSED)
|
|
{
|
|
if (ev.button.button == SDL_BUTTON_WHEELUP)
|
|
{
|
|
mwheelup = totalclock;
|
|
}
|
|
if (ev.button.button == SDL_BUTTON_WHEELDOWN)
|
|
{
|
|
mwheeldown = totalclock;
|
|
}
|
|
mouseb |= (1<<j);
|
|
}
|
|
else
|
|
{
|
|
if (j != SDL_BUTTON_WHEELUP && j != SDL_BUTTON_WHEELDOWN)
|
|
mouseb &= ~(1<<j);
|
|
}
|
|
|
|
if (mousepresscallback)
|
|
mousepresscallback(j+1, ev.button.state == SDL_PRESSED);
|
|
break;
|
|
|
|
case SDL_MOUSEMOTION:
|
|
// SDL <VER> doesn't handle relative mouse movement correctly yet as the cursor still clips to the screen edges
|
|
// so, we call SDL_WarpMouse() to center the cursor and ignore the resulting motion event that occurs
|
|
// <VER> is 1.3 for PK, 1.2 for tueidj
|
|
if (appactive && mousegrab)
|
|
{
|
|
#ifdef GEKKO
|
|
// check if it's a wiimote pointer pretending to be a mouse
|
|
if (ev.motion.state & SDL_BUTTON_X2MASK)
|
|
{
|
|
// the absolute values are used to draw the crosshair
|
|
mouseabsx = ev.motion.x;
|
|
mouseabsy = ev.motion.y;
|
|
// hack: reduce the scale of the "relative" motions
|
|
// to make it act more like a real mouse
|
|
ev.motion.xrel /= 16;
|
|
ev.motion.yrel /= 12;
|
|
}
|
|
#endif
|
|
if (ev.motion.x != xdim>>1 || ev.motion.y != ydim>>1)
|
|
{
|
|
mousex += ev.motion.xrel;
|
|
mousey += ev.motion.yrel;
|
|
#if !defined DEBUGGINGAIDS || MY_DEVELOPER_ID==805120924
|
|
SDL_WarpMouse(xdim>>1, ydim>>1);
|
|
#endif
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SDL_JOYAXISMOTION:
|
|
if (appactive && ev.jaxis.axis < joynumaxes)
|
|
{
|
|
joyaxis[ev.jaxis.axis] = ev.jaxis.value * 10000 / 32767;
|
|
if ((joyaxis[ev.jaxis.axis] < joydead[ev.jaxis.axis])
|
|
&& (joyaxis[ev.jaxis.axis] > -joydead[ev.jaxis.axis]))
|
|
joyaxis[ev.jaxis.axis] = 0;
|
|
else if (joyaxis[ev.jaxis.axis] >= joysatur[ev.jaxis.axis])
|
|
joyaxis[ev.jaxis.axis] = 10000;
|
|
else if (joyaxis[ev.jaxis.axis] <= -joysatur[ev.jaxis.axis])
|
|
joyaxis[ev.jaxis.axis] = -10000;
|
|
else
|
|
joyaxis[ev.jaxis.axis] = joyaxis[ev.jaxis.axis] *
|
|
10000 / joysatur[ev.jaxis.axis];
|
|
}
|
|
break;
|
|
|
|
case SDL_JOYHATMOTION:
|
|
{
|
|
int32_t hatvals[16] =
|
|
{
|
|
-1, // centre
|
|
0, // up 1
|
|
9000, // right 2
|
|
4500, // up+right 3
|
|
18000, // down 4
|
|
-1, // down+up!! 5
|
|
13500, // down+right 6
|
|
-1, // down+right+up!! 7
|
|
27000, // left 8
|
|
27500, // left+up 9
|
|
-1, // left+right!! 10
|
|
-1, // left+right+up!! 11
|
|
22500, // left+down 12
|
|
-1, // left+down+up!! 13
|
|
-1, // left+down+right!! 14
|
|
-1, // left+down+right+up!! 15
|
|
};
|
|
if (appactive && ev.jhat.hat < joynumhats)
|
|
joyhat[ ev.jhat.hat ] = hatvals[ ev.jhat.value & 15 ];
|
|
break;
|
|
}
|
|
|
|
case SDL_JOYBUTTONDOWN:
|
|
case SDL_JOYBUTTONUP:
|
|
if (appactive && ev.jbutton.button < joynumbuttons)
|
|
{
|
|
if (ev.jbutton.state == SDL_PRESSED)
|
|
joyb |= 1 << ev.jbutton.button;
|
|
else
|
|
joyb &= ~(1 << ev.jbutton.button);
|
|
}
|
|
break;
|
|
|
|
case SDL_QUIT:
|
|
quitevent = 1;
|
|
rv=-1;
|
|
break;
|
|
|
|
default:
|
|
//OSD_Printf("Got event (%d)\n", ev.type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// if (mousex|mousey) printf("%d,%d\n",mousex,mousey); ///
|
|
|
|
sampletimer();
|
|
|
|
if (moustat)
|
|
{
|
|
if ((mwheelup) && (mwheelup <= (unsigned)(totalclock - MWHEELTICKS)))
|
|
{
|
|
mouseb &= ~16;
|
|
mwheelup = 0;
|
|
}
|
|
if ((mwheeldown) && (mwheeldown <= (unsigned)(totalclock - MWHEELTICKS)))
|
|
{
|
|
mouseb &= ~32;
|
|
mwheeldown = 0;
|
|
}
|
|
}
|
|
|
|
startwin_idle(NULL);
|
|
|
|
#undef SetKey
|
|
|
|
return rv;
|
|
}
|
|
|
|
inline void idle(void)
|
|
{
|
|
usleep(1000);
|
|
}
|
|
|
|
inline void idle_waitevent(void)
|
|
{
|
|
SDL_WaitEvent(NULL);
|
|
}
|
|
|
|
#if (SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION < 3) // SDL 1.2
|
|
// from SDL HG, modified
|
|
static int32_t SDL_WaitEventTimeout(SDL_Event *event, int32_t timeout)
|
|
{
|
|
uint32_t expiration = 0;
|
|
|
|
if (timeout > 0)
|
|
expiration = SDL_GetTicks() + timeout;
|
|
|
|
for (;;)
|
|
{
|
|
SDL_PumpEvents();
|
|
switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, ~0)) //SDL_FIRSTEVENT, SDL_LASTEVENT)) {
|
|
{
|
|
case -1:
|
|
return 0;
|
|
case 1:
|
|
return 1;
|
|
case 0:
|
|
if (timeout == 0)
|
|
{
|
|
/* Polling and no events, just return */
|
|
return 0;
|
|
}
|
|
if (timeout > 0 && ((int32_t)(SDL_GetTicks() - expiration) >= 0))
|
|
{
|
|
/* Timeout expired and no events */
|
|
return 0;
|
|
}
|
|
SDL_Delay(10);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
inline void idle_waitevent_timeout(uint32_t timeout)
|
|
{
|
|
SDL_WaitEventTimeout(NULL, timeout);
|
|
}
|
|
|
|
#if (SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION < 3) // SDL 1.2
|
|
static int32_t buildkeytranslationtable(void)
|
|
{
|
|
memset(keytranslation,0,sizeof(keytranslation));
|
|
|
|
#define MAP(x,y) keytranslation[x] = y
|
|
MAP(SDLK_BACKSPACE, 0xe);
|
|
MAP(SDLK_TAB, 0xf);
|
|
MAP(SDLK_RETURN, 0x1c);
|
|
MAP(SDLK_PAUSE, 0x59); // 0x1d + 0x45 + 0x9d + 0xc5
|
|
MAP(SDLK_ESCAPE, 0x1);
|
|
MAP(SDLK_SPACE, 0x39);
|
|
MAP(SDLK_EXCLAIM, 0x2); // '1'
|
|
MAP(SDLK_QUOTEDBL, 0x28); // '''
|
|
MAP(SDLK_HASH, 0x4); // '3'
|
|
MAP(SDLK_DOLLAR, 0x5); // '4'
|
|
MAP(37, 0x6); // '5' <-- where's the keysym SDL guys?
|
|
MAP(SDLK_AMPERSAND, 0x8); // '7'
|
|
MAP(SDLK_QUOTE, 0x28); // '''
|
|
MAP(SDLK_LEFTPAREN, 0xa); // '9'
|
|
MAP(SDLK_RIGHTPAREN, 0xb); // '0'
|
|
MAP(SDLK_ASTERISK, 0x9); // '8'
|
|
MAP(SDLK_PLUS, 0xd); // '='
|
|
MAP(SDLK_COMMA, 0x33);
|
|
MAP(SDLK_MINUS, 0xc);
|
|
MAP(SDLK_PERIOD, 0x34);
|
|
MAP(SDLK_SLASH, 0x35);
|
|
MAP(SDLK_0, 0xb);
|
|
MAP(SDLK_1, 0x2);
|
|
MAP(SDLK_2, 0x3);
|
|
MAP(SDLK_3, 0x4);
|
|
MAP(SDLK_4, 0x5);
|
|
MAP(SDLK_5, 0x6);
|
|
MAP(SDLK_6, 0x7);
|
|
MAP(SDLK_7, 0x8);
|
|
MAP(SDLK_8, 0x9);
|
|
MAP(SDLK_9, 0xa);
|
|
MAP(SDLK_COLON, 0x27);
|
|
MAP(SDLK_SEMICOLON, 0x27);
|
|
MAP(SDLK_LESS, 0x33);
|
|
MAP(SDLK_EQUALS, 0xd);
|
|
MAP(SDLK_GREATER, 0x34);
|
|
MAP(SDLK_QUESTION, 0x35);
|
|
MAP(SDLK_AT, 0x3); // '2'
|
|
MAP(SDLK_LEFTBRACKET, 0x1a);
|
|
MAP(SDLK_BACKSLASH, 0x2b);
|
|
MAP(SDLK_RIGHTBRACKET, 0x1b);
|
|
MAP(SDLK_CARET, 0x7); // '7'
|
|
MAP(SDLK_UNDERSCORE, 0xc);
|
|
MAP(SDLK_BACKQUOTE, 0x29);
|
|
MAP(SDLK_a, 0x1e);
|
|
MAP(SDLK_b, 0x30);
|
|
MAP(SDLK_c, 0x2e);
|
|
MAP(SDLK_d, 0x20);
|
|
MAP(SDLK_e, 0x12);
|
|
MAP(SDLK_f, 0x21);
|
|
MAP(SDLK_g, 0x22);
|
|
MAP(SDLK_h, 0x23);
|
|
MAP(SDLK_i, 0x17);
|
|
MAP(SDLK_j, 0x24);
|
|
MAP(SDLK_k, 0x25);
|
|
MAP(SDLK_l, 0x26);
|
|
MAP(SDLK_m, 0x32);
|
|
MAP(SDLK_n, 0x31);
|
|
MAP(SDLK_o, 0x18);
|
|
MAP(SDLK_p, 0x19);
|
|
MAP(SDLK_q, 0x10);
|
|
MAP(SDLK_r, 0x13);
|
|
MAP(SDLK_s, 0x1f);
|
|
MAP(SDLK_t, 0x14);
|
|
MAP(SDLK_u, 0x16);
|
|
MAP(SDLK_v, 0x2f);
|
|
MAP(SDLK_w, 0x11);
|
|
MAP(SDLK_x, 0x2d);
|
|
MAP(SDLK_y, 0x15);
|
|
MAP(SDLK_z, 0x2c);
|
|
MAP(SDLK_DELETE, 0xd3);
|
|
MAP(SDLK_KP0, 0x52);
|
|
MAP(SDLK_KP1, 0x4f);
|
|
MAP(SDLK_KP2, 0x50);
|
|
MAP(SDLK_KP3, 0x51);
|
|
MAP(SDLK_KP4, 0x4b);
|
|
MAP(SDLK_KP5, 0x4c);
|
|
MAP(SDLK_KP6, 0x4d);
|
|
MAP(SDLK_KP7, 0x47);
|
|
MAP(SDLK_KP8, 0x48);
|
|
MAP(SDLK_KP9, 0x49);
|
|
MAP(SDLK_KP_PERIOD, 0x53);
|
|
MAP(SDLK_KP_DIVIDE, 0xb5);
|
|
MAP(SDLK_KP_MULTIPLY, 0x37);
|
|
MAP(SDLK_KP_MINUS, 0x4a);
|
|
MAP(SDLK_KP_PLUS, 0x4e);
|
|
MAP(SDLK_KP_ENTER, 0x9c);
|
|
//MAP(SDLK_KP_EQUALS, );
|
|
MAP(SDLK_UP, 0xc8);
|
|
MAP(SDLK_DOWN, 0xd0);
|
|
MAP(SDLK_RIGHT, 0xcd);
|
|
MAP(SDLK_LEFT, 0xcb);
|
|
MAP(SDLK_INSERT, 0xd2);
|
|
MAP(SDLK_HOME, 0xc7);
|
|
MAP(SDLK_END, 0xcf);
|
|
MAP(SDLK_PAGEUP, 0xc9);
|
|
MAP(SDLK_PAGEDOWN, 0xd1);
|
|
MAP(SDLK_F1, 0x3b);
|
|
MAP(SDLK_F2, 0x3c);
|
|
MAP(SDLK_F3, 0x3d);
|
|
MAP(SDLK_F4, 0x3e);
|
|
MAP(SDLK_F5, 0x3f);
|
|
MAP(SDLK_F6, 0x40);
|
|
MAP(SDLK_F7, 0x41);
|
|
MAP(SDLK_F8, 0x42);
|
|
MAP(SDLK_F9, 0x43);
|
|
MAP(SDLK_F10, 0x44);
|
|
MAP(SDLK_F11, 0x57);
|
|
MAP(SDLK_F12, 0x58);
|
|
MAP(SDLK_NUMLOCK, 0x45);
|
|
MAP(SDLK_CAPSLOCK, 0x3a);
|
|
MAP(SDLK_SCROLLOCK, 0x46);
|
|
MAP(SDLK_RSHIFT, 0x36);
|
|
MAP(SDLK_LSHIFT, 0x2a);
|
|
MAP(SDLK_RCTRL, 0x9d);
|
|
MAP(SDLK_LCTRL, 0x1d);
|
|
MAP(SDLK_RALT, 0xb8);
|
|
MAP(SDLK_LALT, 0x38);
|
|
MAP(SDLK_LSUPER, 0xdb); // win l
|
|
MAP(SDLK_RSUPER, 0xdc); // win r
|
|
MAP(SDLK_PRINT, -2); // 0xaa + 0xb7
|
|
MAP(SDLK_SYSREQ, 0x54); // alt+printscr
|
|
MAP(SDLK_BREAK, 0xb7); // ctrl+pause
|
|
MAP(SDLK_MENU, 0xdd); // win menu?
|
|
#undef MAP
|
|
|
|
return 0;
|
|
}
|
|
#else // if SDL 1.3
|
|
static int32_t buildkeytranslationtable(void)
|
|
{
|
|
memset(keytranslation,0,sizeof(keytranslation));
|
|
|
|
#define MAP(x,y) keytranslation[x] = y
|
|
MAP(SDL_SCANCODE_BACKSPACE, 0xe);
|
|
MAP(SDL_SCANCODE_TAB, 0xf);
|
|
MAP(SDL_SCANCODE_RETURN, 0x1c);
|
|
MAP(SDL_SCANCODE_PAUSE, 0x59); // 0x1d + 0x45 + 0x9d + 0xc5
|
|
MAP(SDL_SCANCODE_ESCAPE, 0x1);
|
|
MAP(SDL_SCANCODE_SPACE, 0x39);
|
|
MAP(SDL_SCANCODE_COMMA, 0x33);
|
|
MAP(SDL_SCANCODE_MINUS, 0xc);
|
|
MAP(SDL_SCANCODE_PERIOD, 0x34);
|
|
MAP(SDL_SCANCODE_SLASH, 0x35);
|
|
MAP(SDL_SCANCODE_0, 0xb);
|
|
MAP(SDL_SCANCODE_1, 0x2);
|
|
MAP(SDL_SCANCODE_2, 0x3);
|
|
MAP(SDL_SCANCODE_3, 0x4);
|
|
MAP(SDL_SCANCODE_4, 0x5);
|
|
MAP(SDL_SCANCODE_5, 0x6);
|
|
MAP(SDL_SCANCODE_6, 0x7);
|
|
MAP(SDL_SCANCODE_7, 0x8);
|
|
MAP(SDL_SCANCODE_8, 0x9);
|
|
MAP(SDL_SCANCODE_9, 0xa);
|
|
MAP(SDL_SCANCODE_SEMICOLON, 0x27);
|
|
MAP(SDL_SCANCODE_EQUALS, 0xd);
|
|
MAP(SDL_SCANCODE_LEFTBRACKET, 0x1a);
|
|
MAP(SDL_SCANCODE_BACKSLASH, 0x2b);
|
|
MAP(SDL_SCANCODE_RIGHTBRACKET, 0x1b);
|
|
MAP(SDL_SCANCODE_A, 0x1e);
|
|
MAP(SDL_SCANCODE_B, 0x30);
|
|
MAP(SDL_SCANCODE_C, 0x2e);
|
|
MAP(SDL_SCANCODE_D, 0x20);
|
|
MAP(SDL_SCANCODE_E, 0x12);
|
|
MAP(SDL_SCANCODE_F, 0x21);
|
|
MAP(SDL_SCANCODE_G, 0x22);
|
|
MAP(SDL_SCANCODE_H, 0x23);
|
|
MAP(SDL_SCANCODE_I, 0x17);
|
|
MAP(SDL_SCANCODE_J, 0x24);
|
|
MAP(SDL_SCANCODE_K, 0x25);
|
|
MAP(SDL_SCANCODE_L, 0x26);
|
|
MAP(SDL_SCANCODE_M, 0x32);
|
|
MAP(SDL_SCANCODE_N, 0x31);
|
|
MAP(SDL_SCANCODE_O, 0x18);
|
|
MAP(SDL_SCANCODE_P, 0x19);
|
|
MAP(SDL_SCANCODE_Q, 0x10);
|
|
MAP(SDL_SCANCODE_R, 0x13);
|
|
MAP(SDL_SCANCODE_S, 0x1f);
|
|
MAP(SDL_SCANCODE_T, 0x14);
|
|
MAP(SDL_SCANCODE_U, 0x16);
|
|
MAP(SDL_SCANCODE_V, 0x2f);
|
|
MAP(SDL_SCANCODE_W, 0x11);
|
|
MAP(SDL_SCANCODE_X, 0x2d);
|
|
MAP(SDL_SCANCODE_Y, 0x15);
|
|
MAP(SDL_SCANCODE_Z, 0x2c);
|
|
MAP(SDL_SCANCODE_DELETE, 0xd3);
|
|
MAP(SDL_SCANCODE_KP_0, 0x52);
|
|
MAP(SDL_SCANCODE_KP_1, 0x4f);
|
|
MAP(SDL_SCANCODE_KP_2, 0x50);
|
|
MAP(SDL_SCANCODE_KP_3, 0x51);
|
|
MAP(SDL_SCANCODE_KP_4, 0x4b);
|
|
MAP(SDL_SCANCODE_KP_5, 0x4c);
|
|
MAP(SDL_SCANCODE_KP_6, 0x4d);
|
|
MAP(SDL_SCANCODE_KP_7, 0x47);
|
|
MAP(SDL_SCANCODE_KP_8, 0x48);
|
|
MAP(SDL_SCANCODE_KP_9, 0x49);
|
|
MAP(SDL_SCANCODE_KP_PERIOD, 0x53);
|
|
MAP(SDL_SCANCODE_KP_DIVIDE, 0xb5);
|
|
MAP(SDL_SCANCODE_KP_MULTIPLY, 0x37);
|
|
MAP(SDL_SCANCODE_KP_MINUS, 0x4a);
|
|
MAP(SDL_SCANCODE_KP_PLUS, 0x4e);
|
|
MAP(SDL_SCANCODE_KP_ENTER, 0x9c);
|
|
//MAP(SDL_SCANCODE_KP_EQUALS, );
|
|
MAP(SDL_SCANCODE_UP, 0xc8);
|
|
MAP(SDL_SCANCODE_DOWN, 0xd0);
|
|
MAP(SDL_SCANCODE_RIGHT, 0xcd);
|
|
MAP(SDL_SCANCODE_LEFT, 0xcb);
|
|
MAP(SDL_SCANCODE_INSERT, 0xd2);
|
|
MAP(SDL_SCANCODE_HOME, 0xc7);
|
|
MAP(SDL_SCANCODE_END, 0xcf);
|
|
MAP(SDL_SCANCODE_PAGEUP, 0xc9);
|
|
MAP(SDL_SCANCODE_PAGEDOWN, 0xd1);
|
|
MAP(SDL_SCANCODE_F1, 0x3b);
|
|
MAP(SDL_SCANCODE_F2, 0x3c);
|
|
MAP(SDL_SCANCODE_F3, 0x3d);
|
|
MAP(SDL_SCANCODE_F4, 0x3e);
|
|
MAP(SDL_SCANCODE_F5, 0x3f);
|
|
MAP(SDL_SCANCODE_F6, 0x40);
|
|
MAP(SDL_SCANCODE_F7, 0x41);
|
|
MAP(SDL_SCANCODE_F8, 0x42);
|
|
MAP(SDL_SCANCODE_F9, 0x43);
|
|
MAP(SDL_SCANCODE_F10, 0x44);
|
|
MAP(SDL_SCANCODE_F11, 0x57);
|
|
MAP(SDL_SCANCODE_F12, 0x58);
|
|
MAP(SDL_SCANCODE_NUMLOCKCLEAR, 0x45);
|
|
MAP(SDL_SCANCODE_CAPSLOCK, 0x3a);
|
|
MAP(SDL_SCANCODE_SCROLLLOCK, 0x46);
|
|
MAP(SDL_SCANCODE_RSHIFT, 0x36);
|
|
MAP(SDL_SCANCODE_LSHIFT, 0x2a);
|
|
MAP(SDL_SCANCODE_RCTRL, 0x9d);
|
|
MAP(SDL_SCANCODE_LCTRL, 0x1d);
|
|
MAP(SDL_SCANCODE_RALT, 0xb8);
|
|
MAP(SDL_SCANCODE_LALT, 0x38);
|
|
MAP(SDL_SCANCODE_LGUI, 0xdb); // win l
|
|
MAP(SDL_SCANCODE_RGUI, 0xdc); // win r
|
|
MAP(SDL_SCANCODE_PRINTSCREEN, -2); // 0xaa + 0xb7
|
|
MAP(SDL_SCANCODE_SYSREQ, 0x54); // alt+printscr
|
|
MAP(SDL_SCANCODE_PAUSE, 0xb7); // ctrl+pause
|
|
MAP(SDL_SCANCODE_MENU, 0xdd); // win menu?
|
|
MAP(SDL_SCANCODE_GRAVE, 0x29); // tilde
|
|
#undef MAP
|
|
|
|
return 0;
|
|
}
|
|
#endif
|