diff --git a/SConstruct b/SConstruct index a5e5ec1c..97b30bce 100644 --- a/SConstruct +++ b/SConstruct @@ -28,7 +28,7 @@ opts.AddVariables( BoolVariable('SYSTEM_MINIZIP', 'Use system minizip instead of static minizip provided with fceux', 0), BoolVariable('LSB_FIRST', 'Least signficant byte first (non-PPC)', 1), BoolVariable('CLANG', 'Compile with llvm-clang instead of gcc', 0), - BoolVariable('SDL2', 'Compile using SDL2 instead of SDL 1.2 (experimental/non-functional)', 0) + BoolVariable('SDL2', 'Compile using SDL2 instead of SDL 1.2 (experimental/non-functional)', 1) ) AddOption('--prefix', dest='prefix', type='string', nargs=1, action='store', metavar='DIR', help='installation prefix') diff --git a/pipelines/linux_build.sh b/pipelines/linux_build.sh index 5acd73b1..118422fa 100755 --- a/pipelines/linux_build.sh +++ b/pipelines/linux_build.sh @@ -32,11 +32,12 @@ sudo apt-get --assume-yes install lua5.1-dev pkg-config --cflags --libs lua5.1 # Install libSDL-1.2 and libSDL-2 -echo '****************************************' -echo 'Install Dependency libsdl1.2-dev' -echo '****************************************' -sudo apt-get --assume-yes install libsdl1.2-dev -sdl-config --cflags --libs +# libSDL-1.2 no long needed +#echo '****************************************' +#echo 'Install Dependency libsdl1.2-dev' +#echo '****************************************' +#sudo apt-get --assume-yes install libsdl1.2-dev +#sdl-config --cflags --libs echo '****************************************' echo 'Install Dependency libsdl2-dev' echo '****************************************' diff --git a/src/drivers/sdl/SConscript b/src/drivers/sdl/SConscript index a8bde4ac..22fbb644 100644 --- a/src/drivers/sdl/SConscript +++ b/src/drivers/sdl/SConscript @@ -13,6 +13,7 @@ source_list = Split( memview.cpp ramwatch.cpp debugger.cpp + glxwin.cpp sdl.cpp sdl-joystick.cpp sdl-sound.cpp @@ -22,8 +23,6 @@ source_list = Split( """) Import('env') -if 'GL' in env['LIBS']: - source_list.append('sdl-opengl.cpp') if env['GTK'] or env['GTK3']: source_list.append('gui.cpp') diff --git a/src/drivers/sdl/config.cpp b/src/drivers/sdl/config.cpp index 0c91e621..9774e0d0 100644 --- a/src/drivers/sdl/config.cpp +++ b/src/drivers/sdl/config.cpp @@ -206,7 +206,7 @@ InitConfig() config->addOption("SDL.LastXRes", 0); config->addOption("SDL.LastYRes", 0); config->addOption('b', "bpp", "SDL.BitsPerPixel", 32); - config->addOption("doublebuf", "SDL.DoubleBuffering", 0); + config->addOption("doublebuf", "SDL.DoubleBuffering", 1); config->addOption("autoscale", "SDL.AutoScale", 1); config->addOption("keepratio", "SDL.KeepRatio", 1); config->addOption("xscale", "SDL.XScale", 1.0); @@ -219,8 +219,8 @@ InitConfig() config->addOption("togglemenu", "SDL.ToggleMenu", 0); // OpenGL options - config->addOption("opengl", "SDL.OpenGL", 0); - config->addOption("openglip", "SDL.OpenGLip", 0); + config->addOption("opengl", "SDL.OpenGL", 1); + config->addOption("openglip", "SDL.OpenGLip", 1); config->addOption("SDL.SpecialFilter", 0); config->addOption("SDL.SpecialFX", 0); config->addOption("SDL.Vsync", 1); diff --git a/src/drivers/sdl/debugger.cpp b/src/drivers/sdl/debugger.cpp index 4aeb27ab..c5982e24 100644 --- a/src/drivers/sdl/debugger.cpp +++ b/src/drivers/sdl/debugger.cpp @@ -141,6 +141,12 @@ struct debuggerWin_t textbuf = NULL; bp_store = NULL; bp_tree = NULL; + bkm_store = NULL; + bkm_tree = NULL; + pc_entry = NULL; + A_entry = NULL; + X_entry = NULL; + Y_entry = NULL; stackview = NULL; stackTextBuf = NULL; ppu_label = NULL; diff --git a/src/drivers/sdl/glxwin.cpp b/src/drivers/sdl/glxwin.cpp new file mode 100644 index 00000000..547df24f --- /dev/null +++ b/src/drivers/sdl/glxwin.cpp @@ -0,0 +1,508 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "glxwin.h" + +static Display *dpy = NULL; +static Window root; +static XVisualInfo *vi = NULL; +static Colormap cmap; +static XSetWindowAttributes swa; +static Window win; +static GLXContext glc = NULL; +static XWindowAttributes gwa; +static XEvent xev; +static GLint double_buffer_ena = 1; + +static GLuint gltexture = 0; +static int spawn_new_window = 0; + +glxwin_shm_t *glx_shm = NULL; + +static int screen_width = 512; +static int screen_height = 512; + +extern GtkWidget *evbox; +extern unsigned int gtk_draw_area_width; +extern unsigned int gtk_draw_area_height; +//************************************************************************ +static glxwin_shm_t *open_shm(void) +{ + int shmId; + glxwin_shm_t *vaddr; + struct shmid_ds ds; + + shmId = shmget( IPC_PRIVATE, sizeof(struct glxwin_shm_t), IPC_CREAT | S_IRWXU | S_IRWXG ); + + if ( shmId == -1 ) + { + perror("Error: GLX shmget Failed:"); + return NULL; + } + printf("Created ShmID: %i \n", shmId ); + + vaddr = (glxwin_shm_t*)shmat( shmId, NULL, 0); + + if ( vaddr == (glxwin_shm_t*)-1 ) + { + perror("Error: GLX shmat Failed:"); + return NULL; + } + memset( vaddr, 0, sizeof(struct glxwin_shm_t)); + + if ( shmctl( shmId, IPC_RMID, &ds ) != 0 ) + { + perror("Error: GLX shmctl IPC_RMID Failed:"); + } + + sem_init( &vaddr->sem, 1, 1 ); + + vaddr->ncol = 256; + vaddr->nrow = 256; + vaddr->pitch = 256 * 4; + + return vaddr; +} +//************************************************************************ +static void getAttrbList( GLint *buf ) +{ + int i=0; + + buf[i] = GLX_RGBA; i++; + buf[i] = GLX_DEPTH_SIZE; i++; + buf[i] = 24; i++; + + if ( double_buffer_ena ) + { + buf[i] = GLX_DOUBLEBUFFER ; i++; + } + buf[i] = None; + +} +//************************************************************************ +static void genTextures( int ipolate ) +{ + glEnable(GL_TEXTURE_2D); + + if ( gltexture ) + { + printf("GL Texture already exists\n"); + } + else + { + glGenTextures(1, &gltexture); + } + printf("Linear Interpolation on GL Texture: %s \n", ipolate ? "Enabled" : "Disabled"); + + glBindTexture(GL_TEXTURE_2D, gltexture); + + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); + +} +//************************************************************************ +static int open_window(void) +{ + GLint att[32]; + + getAttrbList( att ); + + dpy = XOpenDisplay(NULL); + + if (dpy == NULL) { + printf("\n\tcannot connect to X server\n\n"); + exit(0); + } + root = DefaultRootWindow(dpy); + + vi = glXChooseVisual(dpy, 0, att); + + if (vi == NULL) + { + printf("\n\tno appropriate visual found\n\n"); + exit(0); + } + else { + printf("\n\tvisual %p selected\n", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */ + } + + cmap = XCreateColormap(dpy, root, vi->visual, AllocNone); + + swa.colormap = cmap; + swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask; + + win = XCreateWindow(dpy, root, 0, 0, screen_width, screen_height, 0, + vi->depth, InputOutput, vi->visual, + CWColormap | CWEventMask, &swa); + + XMapWindow(dpy, win); + + XStoreName(dpy, win, "FCEUX VIEWPORT"); + + if ( glc == NULL ) + { + glc = glXCreateContext(dpy, vi, NULL, GL_TRUE); + + if ( glc == NULL ) + { + printf("Error: glXCreateContext Failed\n"); + } + } + else + { + printf("GLX Context Already Exists\n"); + } + XFree(vi); vi = NULL; + + glXMakeCurrent(dpy, win, glc); + + genTextures(1); + glDisable(GL_DEPTH_TEST); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Background color to black. + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // In a double buffered setup with page flipping, be sure to clear both buffers. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + return 0; +} +//************************************************************************ +//static void print_pixbuf(void) +//{ +// for (int x=0; x<256; x++) +// { +// for (int y=0; y<256; y++) +// { +// printf("(%i,%i) = %08X \n", x, y, glx_shm->pixbuf[y*256+x] ); +// } +// } +//} +//************************************************************************ +static void render_image(void) +{ + static int null_glc_error = 0; + int l=0, r=glx_shm->ncol; + int t=0, b=glx_shm->nrow; + + float xscale = (float)screen_width / (float)glx_shm->ncol; + float yscale = (float)screen_height / (float)glx_shm->nrow; + + if (xscale < yscale ) + { + yscale = xscale; + } + else + { + xscale = yscale; + } + int rw=(int)((r-l)*xscale); + int rh=(int)((b-t)*yscale); + int sx=(screen_width-rw)/2; + int sy=(screen_height-rh)/2; + + if ( glc == NULL ) + { + if ( !null_glc_error ) + { + printf("Error: GLX Render has NULL Context\n"); + null_glc_error = 1; + } + return; + } + null_glc_error = 0; + + glXMakeCurrent(dpy, win, glc); + //printf("Viewport: (%i,%i) %i %i %i %i \n", + // screen_width, screen_height, sx, sy, rw, rh ); + glViewport(sx, sy, rw, rh); + //glViewport( 0, 0, screen_width, screen_height); + + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0); + + glDisable(GL_DEPTH_TEST); + glClearColor( 0.0, 0.0f, 0.0f, 0.0f); // Background color to black. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_LINE_SMOOTH); + glEnable(GL_TEXTURE_2D); + //glBindTexture(GL_TEXTURE_2D, gltexture); + glBindTexture(GL_TEXTURE_2D, gltexture); + + //print_pixbuf(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, + GL_RGBA, GL_UNSIGNED_BYTE, glx_shm->pixbuf ); + + glBegin(GL_QUADS); + glTexCoord2f(1.0f*l/256, 1.0f*b/256); // Bottom left of picture. + glVertex2f(-1.0f, -1.0f); // Bottom left of target. + + glTexCoord2f(1.0f*r/256, 1.0f*b/256);// Bottom right of picture. + glVertex2f( 1.0f, -1.0f); // Bottom right of target. + + glTexCoord2f(1.0f*r/256, 1.0f*t/256); // Top right of our picture. + glVertex2f( 1.0f, 1.0f); // Top right of target. + + glTexCoord2f(1.0f*l/256, 1.0f*t/256); // Top left of our picture. + glVertex2f(-1.0f, 1.0f); // Top left of target. + glEnd(); + + glDisable(GL_TEXTURE_2D); + + //glColor4f( 1.0, 1.0, 1.0, 1.0 ); + //glLineWidth(5.0); + //glBegin(GL_LINES); + //glVertex2f(-1.0f, -1.0f); // Bottom left of target. + //glVertex2f( 1.0f, 1.0f); // Top right of target. + //glEnd(); + + if ( double_buffer_ena ) + { + glXSwapBuffers( dpy, win ); + } + else + { + glFlush(); + } +} +//************************************************************************ +static int mainWindowLoop(void) +{ + + while( glx_shm->run ) + { + while ( XPending( dpy ) ) + { + XNextEvent(dpy, &xev); + + if (xev.type == Expose) + { + XGetWindowAttributes(dpy, win, &gwa); + //glViewport(0, 0, gwa.width, gwa.height); + //DrawAQuad(); + glXSwapBuffers(dpy, win); + //printf("Expose\n"); + } + else if (xev.type == ConfigureNotify) + { + screen_width = xev.xconfigure.width; + screen_height = xev.xconfigure.height; + + render_image(); + } + else if (xev.type == KeyPress) + { + printf("Key press: %i %08X \n", xev.xkey.keycode, xev.xkey.state ); + + } + else if (xev.type == DestroyNotify) + { + printf("DestroyNotify\n"); + glx_shm->run = 0; + //glXMakeCurrent(dpy, None, NULL); + //glXDestroyContext(dpy, glc); + //XDestroyWindow(dpy, win); + //XCloseDisplay(dpy); + //exit(0); + } + } + + if ( glx_shm->blit_count != glx_shm->render_count ) + { + render_image(); + glx_shm->render_count++; + } + + usleep(10000); + } + + glXMakeCurrent(dpy, None, NULL); + glXDestroyContext(dpy, glc); + XDestroyWindow(dpy, win); + XCloseDisplay(dpy); + exit(0); + return 0; +} +//************************************************************************ +int spawn_glxwin( int flags ) +{ + int pid; + + glx_shm = open_shm(); + + if ( !spawn_new_window ) + { + return 0; + } + pid = fork(); + + if ( pid == 0 ) + { + // Child Process + glx_shm->run = 1; + glx_shm->pid = getpid(); + + printf("Child Process Running: %i\n", glx_shm->pid ); + + open_window(); + + mainWindowLoop(); + + exit(0); + } + else if ( pid > 0 ) + { // Parent Process + + } + else + { + // Error + printf("Error: Failed to Fork GLX Window Process\n"); + } + + return pid; +} +//************************************************************************ +int init_gtk3_GLXContext( int flags ) +{ + GLint att[32]; + + XWindowAttributes xattrb; + + double_buffer_ena = (flags & GLXWIN_DOUBLE_BUFFER) ? 1 : 0; + + getAttrbList( att ); + + printf("Init GLX Context\n"); + printf("Double Buffering: %s\n", double_buffer_ena ? "Enabled" : "Disabled"); + + GdkWindow *gdkWin = gtk_widget_get_window(evbox); + + if ( gdkWin == NULL ) + { + printf("Error: Failed to obtain gdkWindow Handle for evbox widget\n"); + return -1; + } + win = GDK_WINDOW_XID( gdkWin ); + + root = GDK_ROOT_WINDOW(); + + dpy = gdk_x11_get_default_xdisplay(); + + if ( dpy == NULL ) + { + printf("Error: Failed to obtain X Display Handle for evbox widget\n"); + return -1; + } + + if ( XGetWindowAttributes( dpy, win, &xattrb ) == 0 ) + { + printf("Error: XGetWindowAttributes failed\n"); + return -1; + } + //printf("XWinLocation: (%i,%i) \n", xattrb.x, xattrb.y ); + //printf("XWinSize: (%i x %i) \n", xattrb.width, xattrb.height ); + //printf("XWinDepth: %i \n", xattrb.depth ); + //printf("XWinVisual: %p \n", xattrb.visual ); + + vi = glXChooseVisual(dpy, 0, att); + + if (vi == NULL) + { + printf("\n\tno appropriate visual found\n\n"); + exit(0); + } + else { + printf("\n\tvisual %p selected\n", (void *)vi->visualid); /* %p creates hexadecimal output like in glxinfo */ + } + + if ( glc == NULL ) + { + glc = glXCreateContext(dpy, vi, NULL, GL_TRUE); + + if ( glc == NULL ) + { + printf("Error: glXCreateContext Failed\n"); + } + } + XFree(vi); vi = NULL; + + glXMakeCurrent(dpy, win, glc); + + genTextures( flags & GLXWIN_PIXEL_LINEAR_FILTER ? 1 : 0 ); + glDisable(GL_DEPTH_TEST); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Background color to black. + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // In a double buffered setup with page flipping, be sure to clear both buffers. + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + return 0; +} +//************************************************************************ +int destroy_gtk3_GLXContext(void) +{ + if ( dpy != NULL ) + { + glXMakeCurrent(dpy, None, NULL); + } + + if (gltexture) + { + printf("Destroying GLX Texture\n"); + glDeleteTextures(1, &gltexture); + gltexture=0; + } + if ( glc != NULL ) + { + printf("Destroying GLX Context\n"); + glXDestroyContext(dpy, glc); glc = NULL; + } + if ( dpy != NULL ) + { + XSync( dpy, False ); + } + + return 0; +} +//************************************************************************ +int gtk3_glx_render(void) +{ + screen_width = gtk_draw_area_width; + screen_height = gtk_draw_area_height; + + render_image(); + + return 0; +} +//************************************************************************ diff --git a/src/drivers/sdl/glxwin.h b/src/drivers/sdl/glxwin.h new file mode 100644 index 00000000..ba2d8224 --- /dev/null +++ b/src/drivers/sdl/glxwin.h @@ -0,0 +1,77 @@ +// glxwin.cpp +// + +#ifndef __GLXWIN_H__ +#define __GLXWIN_H__ + +#include + +#include + +int spawn_glxwin( int flags ); + +#define GLXWIN_PIXEL_LINEAR_FILTER 0x0001 +#define GLXWIN_DOUBLE_BUFFER 0x0002 + +int init_gtk3_GLXContext( int flags ); + +int destroy_gtk3_GLXContext( void ); + +int gtk3_glx_render(void); + +#define GLX_NES_WIDTH 256 +#define GLX_NES_HEIGHT 256 + +struct glxwin_shm_t +{ + int pid; + int run; + uint32_t render_count; + uint32_t blit_count; + sem_t sem; + + int ncol; + int nrow; + int pitch; + + // Pass Key Events back to GTK Gui + struct + { + int head; + int tail; + + struct { + int type; + int keycode; + int state; + } data[64]; + + } keyEventBuf; + + // Gui Command Event Queue + struct + { + int head; + int tail; + + struct { + int id; + + union { + int i32[4]; + float f32[4]; + } param; + } cmd[64]; + } guiEvent; + + uint32_t pixbuf[65536]; // 256 x 256 + + void clear_pixbuf(void) + { + memset( pixbuf, 0, sizeof(pixbuf) ); + } +}; + +extern glxwin_shm_t *glx_shm; + +#endif diff --git a/src/drivers/sdl/gui.cpp b/src/drivers/sdl/gui.cpp index 63f20ed4..fe82a062 100644 --- a/src/drivers/sdl/gui.cpp +++ b/src/drivers/sdl/gui.cpp @@ -34,11 +34,23 @@ #include #endif +#ifdef APPLEOPENGL +#include +#include +#include +#else +#include +#include +#include +#endif + #include #include #include #include +#include "glxwin.h" + // Fix compliation errors for older version of GTK (Ubuntu 10.04 LTS) #if GTK_MINOR_VERSION < 24 && GTK_MAJOR_VERSION == 2 #define GTK_COMBO_BOX_TEXT GTK_COMBO_BOX @@ -60,18 +72,23 @@ GtkWidget *MainWindow = NULL; GtkWidget *evbox = NULL; GtkWidget *padNoCombo = NULL; GtkWidget *configNoCombo = NULL; -GtkWidget *buttonMappings[10]; +GtkWidget *buttonMappings[10] = { NULL }; static GtkWidget *Menubar = NULL; static GtkRadioMenuItem *stateSlot[10] = { NULL }; bool gtkIsStarted = false; bool menuTogglingEnabled = false; +static int buttonConfigStatus = 0; +static char useCairoDraw = 0; +static int drawAreaGL = 0; unsigned int gtk_draw_area_width = NES_WIDTH; unsigned int gtk_draw_area_height = NES_HEIGHT; -static unsigned int gtk_win_width = 0; -static unsigned int gtk_win_height = 0; -static int gtk_win_menu_ysize = 30; static GtkTreeStore *hotkey_store = NULL; +static cairo_surface_t *cairo_surface = NULL; +static cairo_pattern_t *cairo_pattern = NULL; +static int *cairo_pix_remapper = NULL; +static int numRendLines = 0; +static void cairo_recalc_mapper(void); static gint convertKeypress (GtkWidget * grab, GdkEventKey * event, gpointer user_data); @@ -129,11 +146,13 @@ int configGamepadButton (GtkButton * button, gpointer p) if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button))) return 0; + buttonConfigStatus = 2; + ButtonConfigBegin (); snprintf (buf, sizeof(buf)-1, "SDL.Input.GamePad.%d.", padNo); prefix = buf; - DWaitButton (NULL, &GamePadConfig[padNo][x], configNo); + DWaitButton (NULL, &GamePadConfig[padNo][x], configNo, &buttonConfigStatus ); g_config->setOption (prefix + GamePadNames[x], GamePadConfig[padNo][x].ButtonNum[configNo]); @@ -155,10 +174,16 @@ int configGamepadButton (GtkButton * button, gpointer p) snprintf (buf, sizeof (buf), "%s", ButtonName (&GamePadConfig[padNo][x], configNo)); - gtk_label_set_markup (GTK_LABEL (buttonMappings[x]), buf); + + if ( buttonMappings[x] != NULL ) + { + gtk_label_set_markup (GTK_LABEL (buttonMappings[x]), buf); + } ButtonConfigEnd (); + buttonConfigStatus = 1; + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE); return 0; @@ -166,7 +191,7 @@ int configGamepadButton (GtkButton * button, gpointer p) void resetVideo (void) { - resizeGtkWindow (); + //resizeGtkWindow (); KillVideo (); InitVideo (GameInfo); } @@ -537,11 +562,7 @@ static void hotKeyWindowRefresh (void) g_config->getOption (optionName.c_str (), &keycode); gtk_tree_store_set (hotkey_store, &iter, 0, optionName.c_str (), 1, -#if SDL_VERSION_ATLEAST(2, 0, 0) SDL_GetKeyName (keycode), -#else - SDL_GetKeyName ((SDLKey) keycode), -#endif -1); gtk_tree_store_append (hotkey_store, &iter, NULL); // acquire child iterator } @@ -586,11 +607,8 @@ static gint hotKeyPressCB (GtkTreeView * tree, GdkEventKey * event, hotKeyName.append ( getHotkeyString(indexArray[0]) ); // Convert this keypress from GDK to SDL. -#if SDL_VERSION_ATLEAST(2, 0, 0) sdlkey = GDKToSDLKeyval (event->keyval); -#else - sdlkey = (SDLKey) GDKToSDLKeyval (event->keyval); -#endif + printf ("HotKey Index: %i '%s' %i %i \n", indexArray[0], hotKeyName.c_str (), event->keyval, sdlkey); @@ -677,6 +695,11 @@ void updateGamepadConfig (GtkWidget * w, gpointer p) { int i; char strBuf[128]; + + if ( (padNoCombo == NULL) || (configNoCombo == NULL) ) + { + return; + } int padNo = atoi (gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (padNoCombo))) - 1; @@ -687,39 +710,40 @@ void updateGamepadConfig (GtkWidget * w, gpointer p) for (i = 0; i < 10; i++) { GtkWidget *mappedKey = buttonMappings[i]; - if (GamePadConfig[padNo][i].ButtType[configNo] == - BUTTC_KEYBOARD) + if (GamePadConfig[padNo][i].ButtType[configNo] == BUTTC_KEYBOARD) { -#if SDL_VERSION_ATLEAST(2, 0, 0) snprintf (strBuf, sizeof (strBuf), "%s", SDL_GetKeyName (GamePadConfig[padNo][i]. ButtonNum[configNo])); -#else - snprintf (strBuf, sizeof (strBuf), "%s", - SDL_GetKeyName ((SDLKey) - GamePadConfig[padNo][i]. - ButtonNum[configNo])); -#endif } else sprintf (strBuf, "%s", ButtonName( &GamePadConfig[padNo][i], configNo ) ); - gtk_label_set_text (GTK_LABEL (mappedKey), strBuf); - gtk_label_set_use_markup (GTK_LABEL (mappedKey), TRUE); + if ( mappedKey != NULL ) + { + gtk_label_set_text (GTK_LABEL (mappedKey), strBuf); + gtk_label_set_use_markup (GTK_LABEL (mappedKey), TRUE); + } } } +static void closeGamepadConfig (GtkWidget * w, GdkEvent * e, gpointer p) +{ + gtk_widget_destroy (w); + + padNoCombo = NULL; + configNoCombo = NULL; + + for (int i = 0; i < 10; i++) + { + buttonMappings[i] = NULL; + } + buttonConfigStatus = 0; +} + // creates and opens the gamepad config window (requires GTK 2.24) void openGamepadConfig (void) { - // GTK 2.24 required for this dialog - if (checkGTKVersion (2, 24) == false) - { - // TODO: present this in a GTK MessageBox? - printf (" Warning: GTK >= 2.24 required for this dialog.\nTo configure the gamepads, use \"--inputcfg\" from the command line (ie: \"fceux --inputcfg gamepad1\").\n"); - return; - } - GtkWidget *win; GtkWidget *vbox; GtkWidget *hboxPadNo; @@ -859,8 +883,8 @@ void openGamepadConfig (void) gtk_box_pack_start (GTK_BOX (vbox), buttonFrame, TRUE, TRUE, 5); - g_signal_connect (win, "delete-event", G_CALLBACK (closeDialog), NULL); - g_signal_connect (win, "response", G_CALLBACK (closeDialog), NULL); + g_signal_connect (win, "delete-event", G_CALLBACK (closeGamepadConfig), NULL); + g_signal_connect (win, "response", G_CALLBACK (closeGamepadConfig), NULL); gtk_widget_show_all (win); @@ -869,6 +893,8 @@ void openGamepadConfig (void) g_signal_connect (G_OBJECT (win), "key-release-event", G_CALLBACK (convertKeypress), NULL); + buttonConfigStatus = 1; + return; } @@ -2192,30 +2218,17 @@ static void changeState (GtkRadioMenuItem * radiomenuitem, gpointer user_data) FCEUI_SelectState ((long) user_data, 1); } -#if SDL_VERSION_ATLEAST(2, 0, 0) // SDL 1.2/2.0 compatibility macros #define SDLK_SCROLLOCK SDLK_SCROLLLOCK #define SDLK_PRINT SDLK_PRINTSCREEN #define SDLK_BREAK 0 #define SDLK_COMPOSE 0 #define SDLK_NUMLOCK SDLK_NUMLOCKCLEAR -#define SDLK_KP0 SDLK_KP_0 -#define SDLK_KP1 SDLK_KP_1 -#define SDLK_KP2 SDLK_KP_2 -#define SDLK_KP3 SDLK_KP_3 -#define SDLK_KP4 SDLK_KP_4 -#define SDLK_KP5 SDLK_KP_5 -#define SDLK_KP6 SDLK_KP_6 -#define SDLK_KP7 SDLK_KP_7 -#define SDLK_KP8 SDLK_KP_8 -#define SDLK_KP9 SDLK_KP_9 -#define SDLK_LSUPER SDLK_LGUI -#define SDLK_RSUPER SDLK_RGUI #define SDLK_LMETA 0 #define SDLK_RMETA 0 -#endif + // Adapted from Gens/GS. Converts a GDK key value into an SDL key value. -unsigned short GDKToSDLKeyval (int gdk_key) +unsigned int GDKToSDLKeyval (int gdk_key) { if (!(gdk_key & 0xFF00)) { @@ -2242,7 +2255,7 @@ unsigned short GDKToSDLKeyval (int gdk_key) } // Non-ASCII symbol. - static const uint16_t gdk_to_sdl_table[0x100] = { + static const int gdk_to_sdl_table[0x100] = { // 0x00 - 0x0F 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, @@ -2292,16 +2305,16 @@ unsigned short GDKToSDLKeyval (int gdk_key) 0x0000, 0x0000, SDLK_MODE, SDLK_NUMLOCK, // 0x80 - 0x8F [mostly unused, except for some numeric keypad keys] - SDLK_KP5, 0x0000, 0x0000, 0x0000, + SDLK_KP_5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, SDLK_KP_ENTER, 0x0000, 0x0000, // 0x90 - 0x9F 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, SDLK_KP7, SDLK_KP4, SDLK_KP8, - SDLK_KP6, SDLK_KP2, SDLK_KP9, SDLK_KP3, - SDLK_KP1, SDLK_KP5, SDLK_KP0, SDLK_KP_PERIOD, + 0x0000, SDLK_KP_7, SDLK_KP_4, SDLK_KP_8, + SDLK_KP_6, SDLK_KP_2, SDLK_KP_9, SDLK_KP_3, + SDLK_KP_1, SDLK_KP_5, SDLK_KP_0, SDLK_KP_PERIOD, // 0xA0 - 0xAF 0x0000, 0x0000, 0x0000, 0x0000, @@ -2310,9 +2323,9 @@ unsigned short GDKToSDLKeyval (int gdk_key) 0x0000, SDLK_KP_MINUS, SDLK_KP_PERIOD, SDLK_KP_DIVIDE, // 0xB0 - 0xBF - SDLK_KP0, SDLK_KP1, SDLK_KP2, SDLK_KP3, - SDLK_KP4, SDLK_KP5, SDLK_KP6, SDLK_KP7, - SDLK_KP8, SDLK_KP9, 0x0000, 0x0000, + SDLK_KP_0, SDLK_KP_1, SDLK_KP_2, SDLK_KP_3, + SDLK_KP_4, SDLK_KP_5, SDLK_KP_6, SDLK_KP_7, + SDLK_KP_8, SDLK_KP_9, 0x0000, 0x0000, 0x0000, SDLK_KP_EQUALS, SDLK_F1, SDLK_F2, // 0xC0 - 0xCF @@ -2330,8 +2343,8 @@ unsigned short GDKToSDLKeyval (int gdk_key) // 0xE0 - 0xEF 0x0000, SDLK_LSHIFT, SDLK_RSHIFT, SDLK_LCTRL, SDLK_RCTRL, SDLK_CAPSLOCK, 0x0000, SDLK_LMETA, - SDLK_RMETA, SDLK_LALT, SDLK_RALT, SDLK_LSUPER, - SDLK_RSUPER, 0x0000, 0x0000, 0x0000, + SDLK_RMETA, SDLK_LALT, SDLK_RALT, SDLK_LGUI, + SDLK_RGUI, 0x0000, 0x0000, 0x0000, // 0xF0 - 0xFF [mostly unused, except for Delete] 0x0000, 0x0000, 0x0000, 0x0000, @@ -2340,7 +2353,7 @@ unsigned short GDKToSDLKeyval (int gdk_key) 0x0000, 0x0000, 0x0000, SDLK_DELETE, }; - unsigned short sdl_key = gdk_to_sdl_table[gdk_key & 0xFF]; + unsigned int sdl_key = gdk_to_sdl_table[gdk_key & 0xFF]; if (sdl_key == 0) { // Unhandled GDK key. @@ -2350,10 +2363,11 @@ unsigned short GDKToSDLKeyval (int gdk_key) } // ignore pause and screenshot hotkeys since they is handled by GTK+ as accelerators - if (sdl_key == Hotkeys[HK_PAUSE] || sdl_key == Hotkeys[HK_SCREENSHOT] || - sdl_key == Hotkeys[HK_SAVE_STATE] - || sdl_key == Hotkeys[HK_LOAD_STATE]) + if ( (sdl_key == Hotkeys[HK_PAUSE]) || (sdl_key == Hotkeys[HK_SCREENSHOT]) || + (sdl_key == Hotkeys[HK_SAVE_STATE]) || (sdl_key == Hotkeys[HK_LOAD_STATE]) ) + { return 0; + } return sdl_key; } @@ -2364,24 +2378,18 @@ static gboolean convertKeypress (GtkWidget * grab, GdkEventKey * event, gpointer user_data) { SDL_Event sdlev; - int keystate; -#if SDL_VERSION_ATLEAST(2, 0, 0) SDL_Keycode sdlkey; -#else - SDLKey sdlkey; -#endif + switch (event->type) { case GDK_KEY_PRESS: sdlev.type = SDL_KEYDOWN; sdlev.key.state = SDL_PRESSED; - keystate = 1; break; case GDK_KEY_RELEASE: sdlev.type = SDL_KEYUP; sdlev.key.state = SDL_RELEASED; - keystate = 0; break; default: @@ -2391,30 +2399,42 @@ static gboolean convertKeypress (GtkWidget * grab, GdkEventKey * event, } // Convert this keypress from GDK to SDL. -#if SDL_VERSION_ATLEAST(2, 0, 0) sdlkey = GDKToSDLKeyval (event->keyval); -#else - sdlkey = (SDLKey) GDKToSDLKeyval (event->keyval); -#endif // Create an SDL event from the keypress. + sdlev.key.keysym.scancode = SDL_GetScancodeFromKey(sdlkey); sdlev.key.keysym.sym = sdlkey; + + sdlev.key.keysym.mod = 0; + + if ( event->state & GDK_SHIFT_MASK ) + { + sdlev.key.keysym.mod |= KMOD_SHIFT; + } + if ( event->state & GDK_CONTROL_MASK ) + { + sdlev.key.keysym.mod |= KMOD_CTRL; + } + if ( event->state & GDK_MOD1_MASK ) + { + sdlev.key.keysym.mod |= KMOD_ALT; + } + sdlev.key.repeat = 0; + + + if ( (event->state & GDK_MOD1_MASK) || + getKeyState( SDL_SCANCODE_LALT ) || getKeyState( SDL_SCANCODE_RALT ) ) + { + // Don't pass ALT + Enter to game, as this toggles fullscreen in GTK + if ( sdlkey == SDLK_RETURN ) + { + return FALSE; + } + } + if (sdlkey != 0) { SDL_PushEvent (&sdlev); - - // Only let the emulator handle the key event if this window has the input focus. - //if (keystate == 0 - // || gtk_window_is_active (GTK_WINDOW (MainWindow))) - //{ -#if SDL_VERSION_ATLEAST(2, 0, 0) - // Not sure how to do this yet with SDL 2.0 - // TODO - SDL 2.0 - //SDL_GetKeyboardState(NULL)[SDL_GetScancodeFromKey(sdlkey)] = keystate; -#else - SDL_GetKeyState (NULL)[sdlkey] = keystate; -#endif - //} } // Allow GTK+ to process this key. @@ -2678,7 +2698,7 @@ static GtkWidget *CreateMenubar (GtkWidget * window) gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); //-Options --> Toggle Menubar --------------------- - item = gtk_check_menu_item_new_with_label ("Toggle Menubar (alt)"); + item = gtk_check_menu_item_new_with_label ("Toggle Menubar (Alt+M)"); //gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(item), FALSE); @@ -3004,32 +3024,34 @@ void pushOutputToGTK (const char *str) void showGui (bool b) { if (b) + { + //gtk_window_unmaximize( GTK_WINDOW(MainWindow) ); + gtk_window_unfullscreen( GTK_WINDOW(MainWindow) ); gtk_widget_show_all (MainWindow); + //gtk_window_unfullscreen( GTK_WINDOW(MainWindow) ); + } else - gtk_widget_hide (MainWindow); + { + //gtk_widget_hide (MainWindow); + //gtk_widget_hide (Menubar); + //gtk_window_maximize( GTK_WINDOW(MainWindow) ); + gtk_window_fullscreen( GTK_WINDOW(MainWindow) ); + } } -gint handleKeyRelease (GtkWidget * w, GdkEvent * event, gpointer cb_data) +void toggleMenuVis(void) { if (menuTogglingEnabled) { - static bool menuShown = true; - if (((GdkEventKey *) event)->keyval == GDK_KEY_Alt_L - || ((GdkEventKey *) event)->keyval == GDK_KEY_Alt_R) + if ( gtk_widget_get_visible(Menubar) ) { - if (menuShown) - { - gtk_widget_hide (Menubar); - menuShown = false; - } - else - { - gtk_widget_show (Menubar); - menuShown = true; - } + gtk_widget_hide (Menubar); + } + else + { + gtk_widget_show (Menubar); } } - return 0; }; int GtkMouseData[3] = { 0, 0, 0 }; @@ -3070,37 +3092,424 @@ gint handleMouseClick (GtkWidget * widget, GdkEvent * event, return 0; } +union cairo_pixel_t +{ + uint32_t u32; + uint8_t u8[4]; +}; + +static void transferPix2CairoSurface(void) +{ + union cairo_pixel_t *p; + union cairo_pixel_t *g; + int x, y, i,j, w, h; + + if ( cairo_surface == NULL ) + { + return; + } + //printf("Cairo Pixel ReMap\n"); + cairo_surface_flush( cairo_surface ); + + if ( numRendLines != glx_shm->nrow ) + { + cairo_recalc_mapper(); + } + + w = cairo_image_surface_get_width (cairo_surface); + h = cairo_image_surface_get_height (cairo_surface); + + p = (cairo_pixel_t*)cairo_image_surface_get_data (cairo_surface); + g = (cairo_pixel_t*)glx_shm->pixbuf; + + i=0; + for (y=0; ypixbuf; + + //if ( cairo_surface == NULL ) + //{ + // if ( w ) *w = 0; + // if ( h ) *h = 0; + // if ( s ) *s = 0; + // return NULL; + //} + //cairo_surface_flush( cairo_surface ); + + //if ( w ) + //{ + // *w = cairo_image_surface_get_width (cairo_surface); + //} + //if ( h ) + //{ + // *h = cairo_image_surface_get_height (cairo_surface); + //} + //if ( s ) + //{ + // *s = cairo_image_surface_get_stride(cairo_surface); + //} + + ////return NULL; + //return (uint32_t*)cairo_image_surface_get_data (cairo_surface); +} + +int guiPixelBufferReDraw(void) +{ + glx_shm->blit_count++; + + if ( useCairoDraw ) + { + transferPix2CairoSurface(); + } + else + { + gtk3_glx_render(); + } + + return 0; +} + +int guiClearSurface(void) +{ + uint32_t *p; + int w, h, z, i; + + if ( cairo_surface != NULL ) + { + cairo_surface_flush( cairo_surface ); + + p = (uint32_t*)cairo_image_surface_get_data (cairo_surface); + + w = cairo_image_surface_get_width (cairo_surface); + h = cairo_image_surface_get_height (cairo_surface); + + z = w * h; + for (i=0; ipixbuf; +// +// w2 = width / 2; +// h2 = height / 2; +// +// //printf("W:%i H:%i W/2:%i H/2:%i\n", width, height, w2, h2 ); +// +// i=0; +// for (y=0; yncol; + gh = glx_shm->nrow; + + if ( cairo_pix_remapper != NULL ) + { + ::free( cairo_pix_remapper ); cairo_pix_remapper = NULL; + } + cairo_pix_remapper = (int*)malloc(s); + + if ( cairo_pix_remapper == NULL ) + { + printf("Error: Failed to allocate memory for Pixel Surface Remapper\n"); + return; + } + memset( cairo_pix_remapper, 0, s ); + + sx = (float)w / (float)gw; + sy = (float)h / (float)gh; + + if (sx < sy ) + { + sy = sx; + } + else + { + sx = sy; + } + + sw = (int) ( (float)gw * sx ); + sh = (int) ( (float)gh * sy ); + + llx = (w - sw) / 2; + lly = (h - sh) / 2; + urx = llx + sw; + ury = lly + sh; + + i=0; + for (y=0; y ury) ) + { + for (x=0; x urx) ) + { + cairo_pix_remapper[i] = -1; i++; + } + else + { + nw = (float)(x - llx) / (float)sw; + nh = (float)(y - lly) / (float)sh; + + rx = (int)((float)gw * nw); + ry = (int)((float)gh * nh); + + if ( rx < 0 ) + { + rx = 0; + } + else if ( rx >= GLX_NES_WIDTH ) + { + rx = GLX_NES_WIDTH-1; + } + if ( ry < 0 ) + { + ry = 0; + } + else if ( ry >= GLX_NES_HEIGHT ) + { + ry = GLX_NES_HEIGHT-1; + } + + j = (ry * GLX_NES_WIDTH) + rx; + + cairo_pix_remapper[i] = j; i++; + + //printf("Remap: (%i,%i)=%i (%i,%i)=%i \n", x,y,i, rx,ry,j ); + } + } + } + } + numRendLines = gh; +} + +static void cairo_handle_resize(void) +{ + int w, h; + //cairo_format_t cairo_format; + + if (cairo_surface) + { + cairo_surface_destroy (cairo_surface); cairo_surface = NULL; + } + w = gtk_widget_get_allocated_width( evbox ); + h = gtk_widget_get_allocated_height( evbox ); + + cairo_surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, w, h ); + //cairo_surface = cairo_image_surface_create( CAIRO_FORMAT_RGB24, w, h ); + + //printf("Cairo Surface: %p \n", cairo_surface ); + + //cairo_format = cairo_image_surface_get_format( cairo_surface ); + + if (cairo_pattern) + { + cairo_pattern_destroy (cairo_pattern); cairo_pattern = NULL; + } + cairo_pattern = cairo_pattern_create_for_surface( cairo_surface ); + + //printf("Cairo Format: %i \n", cairo_format ); + + cairo_recalc_mapper(); + + guiClearSurface(); + + transferPix2CairoSurface(); + + //cairo_surface_mark_dirty( cairo_surface ); +} + +int destroy_gui_video( void ) +{ + printf("Destroy GUI Video\n"); + + destroy_cairo_screen(); + + destroy_gtk3_GLXContext(); + + return 0; +} + +int init_gui_video( int use_openGL ) +{ + drawAreaGL = use_openGL; + useCairoDraw = !drawAreaGL; + + if ( use_openGL ) + { + int flags=0; + int linear_interpolation_ena=0; + int double_buffer_ena=0; + + g_config->getOption("SDL.OpenGLip" , &linear_interpolation_ena ); + g_config->getOption("SDL.DoubleBuffering", &double_buffer_ena ); + + if ( linear_interpolation_ena ) flags |= GLXWIN_PIXEL_LINEAR_FILTER; + if ( double_buffer_ena ) flags |= GLXWIN_DOUBLE_BUFFER; + + destroy_cairo_screen(); + init_gtk3_GLXContext( flags ); + } + else + { + destroy_gtk3_GLXContext(); + init_cairo_screen(); + } + return 0; +} + +void init_cairo_screen(void) +{ + cairo_handle_resize(); +} + +void destroy_cairo_screen(void) +{ + if (cairo_pattern) + { + printf("Destroying Cairo Pattern\n"); + cairo_pattern_destroy (cairo_pattern); cairo_pattern = NULL; + } + if (cairo_surface) + { + printf("Destroying Cairo Surface\n"); + cairo_surface_destroy (cairo_surface); cairo_surface = NULL; + } + if ( cairo_pix_remapper != NULL ) + { + printf("Destroying Cairo Pixel Remapper\n"); + ::free( cairo_pix_remapper ); cairo_pix_remapper = NULL; + } +} + + gboolean handle_resize (GtkWindow * win, GdkEvent * event, gpointer data) { // This should handle resizing so the emulation takes up as much // of the GTK window as possible // get new window width/height - int width, height, draw_width, draw_height, winsize_changed = 0; + int width, height, winsize_changed = 0; + width = event->configure.width; height = event->configure.height; //printf ("DEBUG: Configure new window size: %dx%d\n", width, height); - winsize_changed = (width != gtk_win_width) || (height != gtk_win_height); - - gtk_win_width = width; - gtk_win_height = height; + winsize_changed = 0; // get width/height multipliers double xscale = width / (double) NES_WIDTH; double yscale = height / (double) NES_HEIGHT; - draw_width = gtk_win_width; - draw_height = gtk_win_height - gtk_win_menu_ysize; - //printf("DRAW: %ix%i MenuY: %i \n", draw_width, draw_height, gtk_win_menu_ysize ); - if ( (draw_width != gtk_draw_area_width) || (draw_height != gtk_draw_area_height) ) + if ( (width != gtk_draw_area_width) || (height != gtk_draw_area_height) ) { winsize_changed = 1; } - gtk_draw_area_width = draw_width; - gtk_draw_area_height = draw_height; + gtk_draw_area_width = width; + gtk_draw_area_height = height; if ( gtk_draw_area_width < NES_WIDTH ) gtk_draw_area_width = NES_WIDTH; if ( gtk_draw_area_height < NES_HEIGHT ) gtk_draw_area_height = NES_HEIGHT; @@ -3112,17 +3521,22 @@ gboolean handle_resize (GtkWindow * win, GdkEvent * event, gpointer data) if (yscale > xscale) yscale = xscale; + if ( useCairoDraw && winsize_changed ) + { + cairo_handle_resize(); + } + //TODO if openGL make these integers g_config->setOption ("SDL.XScale", xscale); g_config->setOption ("SDL.YScale", yscale); //gtk_widget_realize(evbox); //flushGtkEvents (); - if ( winsize_changed && (GameInfo != 0) ) - { - KillVideo (); - InitVideo (GameInfo); - } + //if ( winsize_changed && (GameInfo != 0) ) + //{ + // KillVideo (); + // InitVideo (GameInfo); + //} gtk_widget_queue_draw( evbox ); @@ -3133,43 +3547,76 @@ gboolean handle_resize (GtkWindow * win, GdkEvent * event, gpointer data) return FALSE; } +// Clear Drawing Area to Black +//static gboolean cairo_clear_cb (GtkWidget * widget, cairo_t * cr, gpointer data) +//{ +// GdkRGBA color; +// GtkStyleContext *context; +// +// context = gtk_widget_get_style_context (widget); +// +// color.red = 0, color.blue = 0; color.green = 0; color.alpha = 1.0; +// +// gtk_render_background( context, cr, 0, 0, gtk_draw_area_width, gtk_draw_area_height ); +// gdk_cairo_set_source_rgba (cr, &color); +// +// cairo_fill (cr); +// cairo_paint (cr); +// +// return FALSE; +//} /* Redraw the screen from the surface. Note that the ::draw * signal receives a ready-to-be-used cairo_t that is already * clipped to only draw the exposed areas of the widget */ + +static gboolean cairo_draw_cb (GtkWidget * widget, cairo_t * cr, gpointer data) +{ + //printf("Cairo Draw\n"); + //cairo_clear_cb( widget, cr, data ); + //cairo_surface_mark_dirty( cairo_surface ); + //cairo_set_source_surface (cr, cairo_surface, 0, 0); + cairo_set_source (cr, cairo_pattern); + cairo_paint (cr); + + return FALSE; +} + static gboolean draw_cb (GtkWidget * widget, cairo_t * cr, gpointer data) { - GdkRGBA color; - GtkStyleContext *context; - gtk_draw_area_width = gtk_widget_get_allocated_width (widget); + gtk_draw_area_width = gtk_widget_get_allocated_width (widget); gtk_draw_area_height = gtk_widget_get_allocated_height (widget); if ( gtk_draw_area_width < NES_WIDTH ) gtk_draw_area_width = NES_WIDTH; if ( gtk_draw_area_height < NES_HEIGHT ) gtk_draw_area_height = NES_HEIGHT; - gtk_win_menu_ysize = gtk_win_height - gtk_draw_area_height; - - // Clear the screen on a window redraw - //if (GameInfo == 0) - //{ - context = gtk_widget_get_style_context (widget); - - color.red = 0, color.blue = 0; color.green = 0; color.alpha = 1.0; - - gtk_render_background( context, cr, 0, 0, gtk_draw_area_width, gtk_draw_area_height ); - gdk_cairo_set_source_rgba (cr, &color); - - cairo_fill (cr); - cairo_paint (cr); - //} + if ( useCairoDraw ) + { + cairo_draw_cb( widget, cr, data ); + } + else + { + gtk3_glx_render(); + } return FALSE; } +static void +drawAreaRealizeCB (GtkWidget *widget, + gpointer user_data) +{ + printf("Draw Area Realize\n"); + + init_gui_video( drawAreaGL ); +} + int InitGTKSubsystem (int argc, char **argv) { + + int s_useOpenGL=0; GtkWidget *vbox; MainWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); @@ -3202,8 +3649,15 @@ int InitGTKSubsystem (int argc, char **argv) // // prg - Bryan Cain, you are the man! - //evbox = gtk_event_box_new(); + #ifdef OPENGL + g_config->getOption("SDL.OpenGL", &s_useOpenGL); + #endif + + drawAreaGL = s_useOpenGL; + useCairoDraw = !drawAreaGL; + evbox = gtk_drawing_area_new (); + gtk_box_pack_start (GTK_BOX (vbox), evbox, TRUE, TRUE, 0); double xscale, yscale; @@ -3223,14 +3677,15 @@ int InitGTKSubsystem (int argc, char **argv) g_signal_connect (G_OBJECT (evbox), "button-release-event", G_CALLBACK (handleMouseClick), NULL); - //g_signal_connect(G_OBJECT(MainWindow), "key-release-event", G_CALLBACK(handleKeyRelease), NULL); - // signal handlers g_signal_connect (MainWindow, "delete-event", quit, NULL); g_signal_connect (MainWindow, "destroy-event", quit, NULL); - // resize handler - g_signal_connect (MainWindow, "configure-event", + + g_signal_connect (evbox, "configure-event", G_CALLBACK (handle_resize), NULL); + + g_signal_connect (evbox, "realize", G_CALLBACK (drawAreaRealizeCB), NULL); + g_signal_connect (evbox, "draw", G_CALLBACK (draw_cb), NULL); gtk_widget_set_size_request (evbox, NES_WIDTH * xscale, diff --git a/src/drivers/sdl/gui.h b/src/drivers/sdl/gui.h index 3edb5782..e824d4a2 100644 --- a/src/drivers/sdl/gui.h +++ b/src/drivers/sdl/gui.h @@ -33,6 +33,7 @@ extern bool gtkIsStarted; int InitGTKSubsystem(int argc, char** argv); void pushOutputToGTK(const char* str); void showGui(bool b); +void toggleMenuVis(void); bool checkGTKVersion(int major_required, int minor_required); @@ -83,7 +84,15 @@ void saveStateAs(); void loadStateFrom(); void quickLoad(); void quickSave(); -unsigned short GDKToSDLKeyval(int gdk_key); +unsigned int GDKToSDLKeyval(int gdk_key); int InitGTKSubsystem(int argc, char** argv); +uint32_t *getGuiPixelBuffer( int *w, int *h, int *s ); +int guiPixelBufferReDraw(void); + +int init_gui_video( int use_openGL ); +int destroy_gui_video( void ); +void init_cairo_screen(void); +void destroy_cairo_screen(void); + #endif // ifndef FCEUX_GUI_H diff --git a/src/drivers/sdl/input.cpp b/src/drivers/sdl/input.cpp index 31cd81fe..f4246e96 100644 --- a/src/drivers/sdl/input.cpp +++ b/src/drivers/sdl/input.cpp @@ -49,7 +49,7 @@ #include /** GLOBALS **/ -int NoWaiting = 1; +int NoWaiting = 0; extern Config *g_config; extern bool bindSavestate, frameAdvanceLagSkip, lagCounterDisplay; @@ -137,32 +137,50 @@ DoCheatSeq () } #include "keyscan.h" -static uint8 *g_keyState = 0; +static uint8 g_keyState[SDL_NUM_SCANCODES]; static int DIPS = 0; -static uint8 keyonce[MKK_COUNT]; +static uint8 keyonce[SDL_NUM_SCANCODES]; #define KEY(__a) g_keyState[MKK(__a)] +int getKeyState( int k ) +{ + if ( (k >= 0) && (k < SDL_NUM_SCANCODES) ) + { + return g_keyState[k]; + } + return 0; +} + static int _keyonly (int a) { - // check for valid key - if (a > SDLK_LAST + 1 || a < 0) - return 0; -#if SDL_VERSION_ATLEAST(2, 0, 0) - if (g_keyState[SDL_GetScancodeFromKey (a)]) -#else - if (g_keyState[a]) -#endif + int sc; + + if ( a < 0 ) { - if (!keyonce[a]) + return 0; + } + + sc = SDL_GetScancodeFromKey(a); + + // check for valid key + if (sc >= SDL_NUM_SCANCODES || sc < 0) + { + return 0; + } + + if (g_keyState[sc]) + { + if (!keyonce[sc]) { - keyonce[a] = 1; + keyonce[sc] = 1; return 1; } } - else { - keyonce[a] = 0; + else + { + keyonce[sc] = 0; } return 0; } @@ -202,24 +220,6 @@ TogglePause () int fullscreen; g_config->getOption ("SDL.Fullscreen", &fullscreen); - // Don't touch grab when in windowed mode - if(fullscreen == 0) - return; - -#if SDL_VERSION_ATLEAST(2, 0, 0) - // TODO - SDL2 -#else - if (FCEUI_EmulationPaused () == 0) - { - SDL_WM_GrabInput (SDL_GRAB_ON); - if(no_cursor) - SDL_ShowCursor (0); - } - else { - SDL_WM_GrabInput (SDL_GRAB_OFF); - SDL_ShowCursor (1); - } -#endif return; } @@ -433,88 +433,53 @@ void FCEUD_LoadStateFrom () unsigned int *GetKeyboard(void) { int size = 256; -#if SDL_VERSION_ATLEAST(2, 0, 0) + Uint8* keystate = (Uint8*)SDL_GetKeyboardState(&size); -#else - Uint8* keystate = SDL_GetKeyState(&size); -#endif + return (unsigned int*)(keystate); } /** * Parse keyboard commands and execute accordingly. */ -static void KeyboardCommands () +static void KeyboardCommands (void) { int is_shift, is_alt; - char *movie_fname = ""; // get the keyboard input -#if SDL_VERSION_ATLEAST(1, 3, 0) - g_keyState = (Uint8*)SDL_GetKeyboardState (NULL); -#else - g_keyState = SDL_GetKeyState (NULL); -#endif // check if the family keyboard is enabled if (CurInputType[2] == SIFC_FKB) { -#if SDL_VERSION_ATLEAST(1, 3, 0) - // TODO - SDL2 - if (0) -#else - if (keyonly (SCROLLLOCK)) -#endif - { - g_fkbEnabled ^= 1; - FCEUI_DispMessage ("Family Keyboard %sabled.", 0, - g_fkbEnabled ? "en" : "dis"); - } -#if SDL_VERSION_ATLEAST(2, 0, 0) - // TODO - SDL2 -#else - SDL_WM_GrabInput (g_fkbEnabled ? SDL_GRAB_ON : SDL_GRAB_OFF); -#endif + if ( g_keyState[SDL_SCANCODE_SCROLLLOCK] ) + { + g_fkbEnabled ^= 1; + FCEUI_DispMessage ("Family Keyboard %sabled.", 0, + g_fkbEnabled ? "en" : "dis"); + } if (g_fkbEnabled) { return; } } -#if SDL_VERSION_ATLEAST(2, 0, 0) - if (g_keyState[SDL_GetScancodeFromKey (SDLK_LSHIFT)] - || g_keyState[SDL_GetScancodeFromKey (SDLK_RSHIFT)]) -#else - if (g_keyState[SDLK_LSHIFT] || g_keyState[SDLK_RSHIFT]) -#endif - is_shift = 1; - else - is_shift = 0; -#if SDL_VERSION_ATLEAST(2, 0, 0) - if (g_keyState[SDL_GetScancodeFromKey (SDLK_LALT)] - || g_keyState[SDL_GetScancodeFromKey (SDLK_RALT)]) -#else - if (g_keyState[SDLK_LALT] || g_keyState[SDLK_RALT]) -#endif + if (g_keyState[SDL_SCANCODE_LSHIFT] || g_keyState[SDL_SCANCODE_RSHIFT]) { - is_alt = 1; -#if !SDL_VERSION_ATLEAST(2, 0, 0) - // workaround for GDK->SDL in GTK problems where ALT release is never - // getting sent - // I know this is sort of an ugly hack to fix this, but the bug is - // rather annoying - // prg318 10/23/11 - int fullscreen; - g_config->getOption ("SDL.Fullscreen", &fullscreen); - if (!fullscreen) - { - g_keyState[SDLK_LALT] = 0; - g_keyState[SDLK_RALT] = 0; - } -#endif + is_shift = 1; } else + { + is_shift = 0; + } + + if (g_keyState[SDL_SCANCODE_LALT] || g_keyState[SDL_SCANCODE_RALT]) + { + is_alt = 1; + } + else + { is_alt = 0; + } if (_keyonly (Hotkeys[HK_TOGGLE_BG])) @@ -530,37 +495,50 @@ static void KeyboardCommands () } // Alt-Enter to toggle full-screen - if (keyonly (ENTER) && is_alt) + // This is already handled by GTK Accelerator + //if (keyonly (ENTER) && is_alt) + //{ + // ToggleFS (); + //} + // + + // Alt-M to toggle Main Menu Visibility + if ( is_alt ) { - ToggleFS (); + if (keyonly (M)) + { + toggleMenuVis(); + } } - - // Toggle Movie auto-backup - if (keyonly (M) && is_shift) + if ( is_shift ) { - autoMovieBackup ^= 1; - FCEUI_DispMessage ("Automatic movie backup %sabled.", 0, - autoMovieBackup ? "en" : "dis"); + if (keyonly (M)) + { + autoMovieBackup ^= 1; + FCEUI_DispMessage ("Automatic movie backup %sabled.", 0, + autoMovieBackup ? "en" : "dis"); + } } - // Start recording an FM2 movie on Alt+R - if (keyonly (R) && is_alt) + if ( is_alt ) { - FCEUD_MovieRecordTo (); - } - - // Save a state from a file - if (keyonly (S) && is_alt) - { - FCEUD_SaveStateAs (); - } - - // Load a state from a file - if (keyonly (L) && is_alt) - { - FCEUD_LoadStateFrom (); + // Start recording an FM2 movie on Alt+R + if (keyonly (R)) + { + FCEUD_MovieRecordTo (); + } + // Save a state from a file + if (keyonly (S)) + { + FCEUD_SaveStateAs (); + } + // Load a state from a file + if (keyonly (L)) + { + FCEUD_LoadStateFrom (); + } } // Famicom disk-system games @@ -594,10 +572,9 @@ static void KeyboardCommands () { if (is_shift) { - movie_fname = - const_cast (FCEU_MakeFName (FCEUMKF_MOVIE, 0, 0).c_str ()); - FCEUI_printf ("Recording movie to %s\n", movie_fname); - FCEUI_SaveMovie (movie_fname, MOVIE_FLAG_NONE, L""); + std::string movie_fname = FCEU_MakeFName (FCEUMKF_MOVIE, 0, 0); + FCEUI_printf ("Recording movie to %s\n", movie_fname.c_str() ); + FCEUI_SaveMovie(movie_fname.c_str() , MOVIE_FLAG_NONE, L""); } else { @@ -683,14 +660,14 @@ static void KeyboardCommands () } // Toggle throttling - NoWaiting &= ~1; - if (g_keyState[Hotkeys[HK_TURBO]]) + if ( _keyonly(Hotkeys[HK_TURBO]) ) { - NoWaiting |= 1; + NoWaiting ^= 1; + //printf("NoWaiting: 0x%04x\n", NoWaiting ); } static bool frameAdvancing = false; - if (g_keyState[Hotkeys[HK_FRAME_ADVANCE]]) + if ( _keyonly(Hotkeys[HK_FRAME_ADVANCE])) { if (frameAdvancing == false) { @@ -968,6 +945,10 @@ void GetMouseRelative (int32 (&d)[3]) d[2] = md[2]; // buttons } +//static void checkKeyBoardState( int scanCode ) +//{ +// printf("Key State is: %i \n", g_keyState[ scanCode ] ); +//} /** * Handles outstanding SDL events. */ @@ -995,6 +976,15 @@ UpdatePhysicalInput () FCEU_printf ("Warning: unknown hotkey event %d\n", event.user.code); } + break; + case SDL_KEYDOWN: + case SDL_KEYUP: + //printf("SDL_Event.type: %i Keysym: %i ScanCode: %i\n", + // event.type, event.key.keysym.sym, event.key.keysym.scancode ); + + g_keyState[ event.key.keysym.scancode ] = (event.type == SDL_KEYDOWN) ? 1 : 0; + //checkKeyBoardState( event.key.keysym.scancode ); + break; default: break; } @@ -1019,66 +1009,20 @@ int ButtonConfigBegin () g_config->getOption ("SDL.NoGUI", &noGui); if (noGui == 1) { - SDL_QuitSubSystem (SDL_INIT_VIDEO); + //SDL_QuitSubSystem (SDL_INIT_VIDEO); bcpv = KillVideo (); } #else // XXX soules - why are we doing this right before KillVideo()? - SDL_QuitSubSystem (SDL_INIT_VIDEO); + //SDL_QuitSubSystem (SDL_INIT_VIDEO); // shut down the video and joystick subsystems bcpv = KillVideo (); #endif - SDL_Surface *screen; + //SDL_Surface *screen; bcpj = KillJoysticks (); - // reactivate the video subsystem - if (!SDL_WasInit (SDL_INIT_VIDEO)) - { - if (!bcpv) - { - InitVideo (GameInfo); - } - else - { -#if defined(_GTK) && defined(SDL_VIDEO_DRIVER_X11) - if (noGui == 0) - { - while (gtk_events_pending ()) - gtk_main_iteration_do (FALSE); - - char SDL_windowhack[128]; - if (gtk_widget_get_window (evbox)) - sprintf (SDL_windowhack, "SDL_WINDOWID=%u", - (unsigned int) GDK_WINDOW_XID (gtk_widget_get_window (evbox))); -#if SDL_VERSION_ATLEAST(2, 0, 0) - // TODO - SDL2 -#else - SDL_putenv (SDL_windowhack); -#endif - } -#endif - if (SDL_InitSubSystem (SDL_INIT_VIDEO) == -1) - { - FCEUD_Message (SDL_GetError ()); - return 0; - } - - // set the screen and notify the user of button configuration -#if SDL_VERSION_ATLEAST(2, 0, 0) - // TODO - SDL2 -#else - screen = SDL_SetVideoMode (420, 200, 8, 0); - if ( screen == NULL ) - { - printf("Error: SDL_SetVideoMode Failed\n"); - } - SDL_WM_SetCaption ("Button Config", 0); -#endif - } - } - // XXX soules - why did we shut this down? // initialize the joystick subsystem InitJoysticks (); @@ -1120,13 +1064,8 @@ DTestButton (ButtConfig * bc) { if (bc->ButtType[x] == BUTTC_KEYBOARD) { -#if SDL_VERSION_ATLEAST(2, 0, 0) if (g_keyState[SDL_GetScancodeFromKey (bc->ButtonNum[x])]) { -#else - if (g_keyState[bc->ButtonNum[x]]) - { -#endif return 1; } } @@ -1137,8 +1076,8 @@ DTestButton (ButtConfig * bc) return 1; } } - } - return 0; + } + return 0; } @@ -1148,15 +1087,9 @@ DTestButton (ButtConfig * bc) #define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()} ButtConfig GamePadConfig[4][10] = { -#if SDL_VERSION_ATLEAST(2, 0, 0) /* Gamepad 1 */ {MK (KP_3), MK (KP_2), MK (SLASH), MK (ENTER), MK (W), MK (Z), MK (A), MK (S), MKZ (), MKZ ()}, -#else - /* Gamepad 1 */ - {MK (KP3), MK (KP2), MK (SLASH), MK (ENTER), - MK (W), MK (Z), MK (A), MK (S), MKZ (), MKZ ()}, -#endif /* Gamepad 2 */ GPZ (), @@ -1200,6 +1133,7 @@ UpdateGamepad(void) { if (DTestButton (&GamePadConfig[wg][x])) { + //printf("GamePad%i Button Hit: %i \n", wg, x ); if(opposite_dirs == 0) { // test for left+right and up+down @@ -1426,6 +1360,8 @@ void InitInputInterface () int x; int attrib; + memset( g_keyState, 0, sizeof(g_keyState) ); + for (t = 0, x = 0; x < 2; x++) { attrib = 0; @@ -1671,11 +1607,7 @@ const char * ButtonName (const ButtConfig * bc, int which) switch (bc->ButtType[which]) { case BUTTC_KEYBOARD: -#if SDL_VERSION_ATLEAST(2,0,0) return SDL_GetKeyName (bc->ButtonNum[which]); -#else - return SDL_GetKeyName ((SDLKey) bc->ButtonNum[which]); -#endif break; case BUTTC_JOYSTICK: { @@ -1731,7 +1663,7 @@ const char * ButtonName (const ButtConfig * bc, int which) * Waits for a button input and returns the information as to which * button was pressed. Used in button configuration. */ -int DWaitButton (const uint8 * text, ButtConfig * bc, int wb) +int DWaitButton (const uint8 * text, ButtConfig * bc, int wb, int *buttonConfigStatus ) { SDL_Event event; static int32 LastAx[64][64]; @@ -1741,11 +1673,8 @@ int DWaitButton (const uint8 * text, ButtConfig * bc, int wb) { std::string title = "Press a key for "; title += (const char *) text; -#if SDL_VERSION_ATLEAST(2,0,0) // TODO - SDL2 -#else - SDL_WM_SetCaption (title.c_str (), 0); -#endif + //SDL_WM_SetCaption (title.c_str (), 0); puts ((const char *) text); } @@ -1825,6 +1754,16 @@ int DWaitButton (const uint8 * text, ButtConfig * bc, int wb) } if (done) break; + + // If the button config window is Closed, + // get out of loop. + if ( buttonConfigStatus != NULL ) + { + if ( *buttonConfigStatus == 0 ) + { + break; + } + } } return (0); @@ -1846,7 +1785,7 @@ ConfigButton (char *text, ButtConfig * bc) for (wc = 0; wc < MAXBUTTCONFIG; wc++) { sprintf ((char *) buf, "%s (%d)", text, wc + 1); - DWaitButton (buf, bc, wc); + DWaitButton (buf, bc, wc, NULL); if (wc && bc->ButtType[wc] == bc->ButtType[wc - 1] && diff --git a/src/drivers/sdl/input.h b/src/drivers/sdl/input.h index bd3d4994..2a1a2d85 100644 --- a/src/drivers/sdl/input.h +++ b/src/drivers/sdl/input.h @@ -7,7 +7,8 @@ typedef struct { uint8 ButtType[MAXBUTTCONFIG]; uint8 DeviceNum[MAXBUTTCONFIG]; - uint16 ButtonNum[MAXBUTTCONFIG]; + //uint16 ButtonNum[MAXBUTTCONFIG]; + int ButtonNum[MAXBUTTCONFIG]; uint32 NumC; //uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */ } ButtConfig; @@ -19,10 +20,11 @@ extern ARGPSTRUCT InputArgs[]; extern int Hotkeys[]; void ParseGIInput(FCEUGI *GI); void setHotKeys(); +int getKeyState( int k ); int ButtonConfigBegin(); void ButtonConfigEnd(); void ConfigButton(char *text, ButtConfig *bc); -int DWaitButton(const uint8 *text, ButtConfig *bc, int wb); +int DWaitButton(const uint8 *text, ButtConfig *bc, int wb, int *buttonConfigStatus = NULL); #define BUTTC_KEYBOARD 0x00 #define BUTTC_JOYSTICK 0x01 diff --git a/src/drivers/sdl/keyscan.h b/src/drivers/sdl/keyscan.h index 0a73804b..b3973c20 100644 --- a/src/drivers/sdl/keyscan.h +++ b/src/drivers/sdl/keyscan.h @@ -42,7 +42,3 @@ #define SDLK_SCROLLLOCK SDLK_SCROLLOCK /* I guess the SDL people don't like lots of Ls... */ #define SDLK_GRAVE SDLK_BACKQUOTE #define MKK(k) SDLK_##k -#if SDL_VERSION_ATLEAST(2, 0, 0) -#define SDLK_LAST SDL_NUM_SCANCODES -#endif -#define MKK_COUNT (SDLK_LAST+1) diff --git a/src/drivers/sdl/sdl-opengl.cpp b/src/drivers/sdl/sdl-opengl.cpp deleted file mode 100644 index ce8562fc..00000000 --- a/src/drivers/sdl/sdl-opengl.cpp +++ /dev/null @@ -1,251 +0,0 @@ -#define GL_GLEXT_LEGACY - -#include "sdl.h" -#include "sdl-opengl.h" -#include "../common/vidblit.h" -#include "../../utils/memory.h" - -#ifdef APPLEOPENGL -#include -#include -#include -#else -#include -#include -#include -#endif -#include -#include - -#ifndef APIENTRY -#define APIENTRY -#endif - -static GLuint textures[2]={0,0}; // Normal image, scanline overlay. - -static int left,right,top,bottom; // right and bottom are not inclusive. -static int scanlines; -static void *HiBuffer; - -typedef void APIENTRY (*glColorTableEXT_Func)(GLenum target, - GLenum internalformat, GLsizei width, GLenum format, GLenum type, - const GLvoid *table); -glColorTableEXT_Func p_glColorTableEXT; - -void -SetOpenGLPalette(uint8 *data) -{ - if(!HiBuffer) { - glBindTexture(GL_TEXTURE_2D, textures[0]); - p_glColorTableEXT(GL_TEXTURE_2D, GL_RGB, 256, - GL_RGBA, GL_UNSIGNED_BYTE, data); - } else { - SetPaletteBlitToHigh((uint8*)data); - } -} - -void -BlitOpenGL(uint8 *buf) -{ - glClear(GL_COLOR_BUFFER_BIT); - glBindTexture(GL_TEXTURE_2D, textures[0]); - - if(HiBuffer) { - Blit8ToHigh(buf, (uint8*)HiBuffer, 256, 240, 256*4, 1, 1); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, - GL_RGBA, GL_UNSIGNED_BYTE, HiBuffer); - } - else { - //glPixelStorei(GL_UNPACK_ROW_LENGTH, 256); - glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, 256, 256, 0, - GL_COLOR_INDEX,GL_UNSIGNED_BYTE,buf); - } - - glBegin(GL_QUADS); - glTexCoord2f(1.0f*left/256, 1.0f*bottom/256); // Bottom left of picture. - glVertex2f(-1.0f, -1.0f); // Bottom left of target. - - glTexCoord2f(1.0f*right/256, 1.0f*bottom/256);// Bottom right of picture. - glVertex2f( 1.0f, -1.0f); // Bottom right of target. - - glTexCoord2f(1.0f*right/256, 1.0f*top/256); // Top right of our picture. - glVertex2f( 1.0f, 1.0f); // Top right of target. - - glTexCoord2f(1.0f*left/256, 1.0f*top/256); // Top left of our picture. - glVertex2f(-1.0f, 1.0f); // Top left of target. - glEnd(); - - //glDisable(GL_BLEND); - if(scanlines) { - glEnable(GL_BLEND); - - glBindTexture(GL_TEXTURE_2D, textures[1]); - glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA); - - glBegin(GL_QUADS); - - glTexCoord2f(1.0f*left/256, - 1.0f*bottom/256); // Bottom left of our picture. - glVertex2f(-1.0f, -1.0f); // Bottom left of target. - - glTexCoord2f(1.0f*right/256, - 1.0f*bottom/256); // Bottom right of our picture. - glVertex2f( 1.0f, -1.0f); // Bottom right of target. - - glTexCoord2f(1.0f*right/256, - 1.0f*top/256); // Top right of our picture. - glVertex2f( 1.0f, 1.0f); // Top right of target. - - glTexCoord2f(1.0f*left/256, - 1.0f*top/256); // Top left of our picture. - glVertex2f(-1.0f, 1.0f); // Top left of target. - - glEnd(); - glDisable(GL_BLEND); - } - SDL_GL_SwapBuffers(); -} - -void -KillOpenGL(void) -{ - if(textures[0]) { - glDeleteTextures(2, &textures[0]); - } - textures[0]=0; - if(HiBuffer) { - free(HiBuffer); - HiBuffer=0; - } -} -/* Rectangle, left, right(not inclusive), top, bottom(not inclusive). */ - -int -InitOpenGL(int l, - int r, - int t, - int b, - double xscale, - double yscale, - int efx, - int ipolate, - int stretchx, - int stretchy, - SDL_Surface *screen) -{ - const char *extensions; - -#define LFG(x) if(!(##x = (x##_Func) SDL_GL_GetProcAddress(#x))) return(0); - -#define LFGN(x) p_##x = (x##_Func) SDL_GL_GetProcAddress(#x) - -// LFG(glBindTexture); - LFGN(glColorTableEXT); -// LFG(glTexImage2D); -// LFG(glBegin); -// LFG(glVertex2f); -// LFG(glTexCoord2f); -// LFG(glEnd); -// LFG(glEnable); -// LFG(glBlendFunc); -// LFG(glGetString); -// LFG(glViewport); -// LFG(glGenTextures); -// LFG(glDeleteTextures); -// LFG(glTexParameteri); -// LFG(glClearColor); -// LFG(glLoadIdentity); -// LFG(glClear); -// LFG(glMatrixMode); -// LFG(glDisable); - - left=l; - right=r; - top=t; - bottom=b; - - HiBuffer=0; - - extensions=(const char*)glGetString(GL_EXTENSIONS); - - if((efx&2) || !extensions || !p_glColorTableEXT || !strstr(extensions,"GL_EXT_paletted_texture")) - { - if(!(efx&2)) // Don't want to print out a warning message in this case... - FCEU_printf("Paletted texture extension not found. Using slower texture format...\n"); - HiBuffer=FCEU_malloc(4*256*256); - memset(HiBuffer,0x00,4*256*256); - #ifndef LSB_FIRST - InitBlitToHigh(4,0xFF000000,0xFF0000,0xFF00,efx&2,0,0); - #else - InitBlitToHigh(4,0xFF,0xFF00,0xFF0000,efx&2,0,0); - #endif - } - - if(screen->flags & SDL_FULLSCREEN) - { - xscale=(double)screen->w / (double)(r-l); - yscale=(double)screen->h / (double)(b-t); - if(xscalew-rw)/2; // Start x - int sy=(screen->h-rh)/2; // Start y - - if(stretchx) { sx=0; rw=screen->w; } - if(stretchy) { sy=0; rh=screen->h; } - glViewport(sx, sy, rw, rh); - } - glGenTextures(2, &textures[0]); - scanlines=0; - - if(efx&1) - { - uint8 *buf; - int x,y; - - scanlines=1; - - glBindTexture(GL_TEXTURE_2D, textures[1]); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST); - - buf=(uint8*)FCEU_dmalloc(256*(256*2)*4); - - for(y=0;y<(256*2);y++) - for(x=0;x<256;x++) - { - buf[y*256*4+x*4]=0; - buf[y*256*4+x*4+1]=0; - buf[y*256*4+x*4+2]=0; - buf[y*256*4+x*4+3]=(y&1)?0x00:0xFF; //?0xa0:0xFF; // <-- Pretty - //buf[y*256+x]=(y&1)?0x00:0xFF; - } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, (scanlines==2)?256*4:512, 0, - GL_RGBA,GL_UNSIGNED_BYTE,buf); - FCEU_dfree(buf); - } - glBindTexture(GL_TEXTURE_2D, textures[0]); - - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); - glEnable(GL_TEXTURE_2D); - glDisable(GL_DEPTH_TEST); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Background color to black. - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - // In a double buffered setup with page flipping, be sure to clear both buffers. - glClear(GL_COLOR_BUFFER_BIT); - SDL_GL_SwapBuffers(); - glClear(GL_COLOR_BUFFER_BIT); - SDL_GL_SwapBuffers(); - - return 1; -} diff --git a/src/drivers/sdl/sdl-opengl.h b/src/drivers/sdl/sdl-opengl.h deleted file mode 100644 index 0e88900f..00000000 --- a/src/drivers/sdl/sdl-opengl.h +++ /dev/null @@ -1,6 +0,0 @@ -void SetOpenGLPalette(uint8 *data); -void BlitOpenGL(uint8 *buf); -void KillOpenGL(void); -int InitOpenGL(int l, int r, int t, int b, double xscale,double yscale, int efx, int ipolate, - int stretchx, int stretchy, SDL_Surface *screen); - diff --git a/src/drivers/sdl/sdl-sound.cpp b/src/drivers/sdl/sdl-sound.cpp index 36830ca3..00b7c9a6 100644 --- a/src/drivers/sdl/sdl-sound.cpp +++ b/src/drivers/sdl/sdl-sound.cpp @@ -75,25 +75,21 @@ InitSound() { int sound, soundrate, soundbufsize, soundvolume, soundtrianglevolume, soundsquare1volume, soundsquare2volume, soundnoisevolume, soundpcmvolume, soundq; SDL_AudioSpec spec; + const char *driverName; g_config->getOption("SDL.Sound", &sound); - if(!sound) { + if (!sound) + { return 0; } memset(&spec, 0, sizeof(spec)); - if(SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { + if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) + { puts(SDL_GetError()); KillSound(); return 0; } - char driverName[8]; -#if SDL_VERSION_ATLEAST(2, 0, 0) - // TODO - SDL 2 -#else - SDL_AudioDriverName(driverName, 8); - fprintf(stderr, "Loading SDL sound with %s driver...\n", driverName); -#endif // load configuration variables g_config->getOption("SDL.Sound.Rate", &soundrate); @@ -117,21 +113,33 @@ InitSound() // For safety, set a bare minimum: if (s_BufferSize < spec.samples * 2) - s_BufferSize = spec.samples * 2; + { + s_BufferSize = spec.samples * 2; + } s_Buffer = (int *)FCEU_dmalloc(sizeof(int) * s_BufferSize); + if (!s_Buffer) + { return 0; + } s_BufferRead = s_BufferWrite = s_BufferIn = 0; - if(SDL_OpenAudio(&spec, 0) < 0) + if (SDL_OpenAudio(&spec, 0) < 0) { puts(SDL_GetError()); KillSound(); return 0; - } + } SDL_PauseAudio(0); + driverName = SDL_GetCurrentAudioDriver(); + + if ( driverName ) + { + fprintf(stderr, "Loading SDL sound with %s driver...\n", driverName); + } + FCEUI_SetSoundVolume(soundvolume); FCEUI_SetSoundQuality(soundq); FCEUI_Sound(soundrate); diff --git a/src/drivers/sdl/sdl-throttle.cpp b/src/drivers/sdl/sdl-throttle.cpp index 6832f954..498d4fe7 100644 --- a/src/drivers/sdl/sdl-throttle.cpp +++ b/src/drivers/sdl/sdl-throttle.cpp @@ -75,9 +75,13 @@ SpeedThrottle() else InFrame = 0; - /*fprintf(stderr, "attempting to sleep %Ld ms, frame complete=%s\n", - time_left, InFrame?"no":"yes");*/ - SDL_Delay(time_left); + //fprintf(stderr, "attempting to sleep %Ld ms, frame complete=%s\n", + // time_left, InFrame?"no":"yes"); + + if ( time_left > 0 ) + { + SDL_Delay(time_left); + } if(!InFrame) { diff --git a/src/drivers/sdl/sdl-video.cpp b/src/drivers/sdl/sdl-video.cpp index a101bd61..2b5e44f2 100644 --- a/src/drivers/sdl/sdl-video.cpp +++ b/src/drivers/sdl/sdl-video.cpp @@ -22,7 +22,7 @@ /// \brief Handles the graphical game display for the SDL implementation. #include "sdl.h" -#include "sdl-opengl.h" +#include "glxwin.h" #include "../common/vidblit.h" #include "../../fceu.h" #include "../../version.h" @@ -55,31 +55,25 @@ extern Config *g_config; // STATIC GLOBALS -static SDL_Surface *s_screen = NULL; - -static SDL_Surface *s_BlitBuf; // Buffer when using hardware-accelerated blits. -static SDL_Surface *s_IconSurface = NULL; - -static int s_curbpp; +static int s_curbpp = 0; static int s_srendline, s_erendline; static int s_tlines; -static int s_inited; +static int s_inited = 0; #ifdef OPENGL -static int s_useOpenGL; +static int s_useOpenGL = 0; #endif -static double s_exs, s_eys; -static int s_eefx; -static int s_clipSides; -static int s_fullscreen; -static int noframe; -static int s_nativeWidth = -1; -static int s_nativeHeight = -1; +static double s_exs = 1.0, s_eys = 1.0; +static int s_eefx = 0; +static int s_clipSides = 0; +static int s_fullscreen = 0; +static int noframe = 0; +static int initBlitToHighDone = 0; #define NWIDTH (256 - (s_clipSides ? 16 : 0)) #define NOFFSET (s_clipSides ? 8 : 0) -static int s_paletterefresh; +static int s_paletterefresh = 1; extern bool MaxSpeed; @@ -99,29 +93,29 @@ bool FCEUD_ShouldDrawInputAids() int KillVideo() { - // if the IconSurface has been initialized, destroy it - if(s_IconSurface) { - SDL_FreeSurface(s_IconSurface); - s_IconSurface=0; + //printf("Killing Video\n"); + + if ( glx_shm != NULL ) + { + glx_shm->clear_pixbuf(); } - // return failure if the video system was not initialized - if(s_inited == 0) - return -1; - - // if the rest of the system has been initialized, shut it down -#ifdef OPENGL - // check for OpenGL and shut it down - if(s_useOpenGL) - KillOpenGL(); - else -#endif - // shut down the system that converts from 8 to 16/32 bpp - if(s_curbpp > 8) - KillBlitToHigh(); + destroy_gui_video(); + // return failure if the video system was not initialized + if (s_inited == 0) + return -1; + + // if the rest of the system has been initialized, shut it down +// // shut down the system that converts from 8 to 16/32 bpp +// if (s_curbpp > 8) +// { +// KillBlitToHigh(); +// } + + // SDL Video system is not used. // shut down the SDL video sub-system - SDL_QuitSubSystem(SDL_INIT_VIDEO); + //SDL_QuitSubSystem(SDL_INIT_VIDEO); s_inited = 0; return 0; @@ -129,7 +123,7 @@ KillVideo() // this variable contains information about the special scaling filters -static int s_sponge; +static int s_sponge = 0; /** * These functions determine an appropriate scale factor for fullscreen/ @@ -152,24 +146,8 @@ void FCEUD_VideoChanged() PAL = 0; // NTSC and Dendy } -#if SDL_VERSION_ATLEAST(2, 0, 0) int InitVideo(FCEUGI *gi) { - // This is a big TODO. Stubbing this off into its own function, - // as the SDL surface routines have changed drastically in SDL2 - // TODO - SDL2 -} -#else -/** - * Attempts to initialize the graphical video display. Returns 0 on - * success, -1 on failure. - */ -int -InitVideo(FCEUGI *gi) -{ - // XXX soules - const? is this necessary? - const SDL_VideoInfo *vinf; - int error, flags = 0; int doublebuf, xstretch, ystretch, xres, yres, show_fps; FCEUI_printf("Initializing video..."); @@ -180,7 +158,7 @@ InitVideo(FCEUGI *gi) #ifdef OPENGL g_config->getOption("SDL.OpenGL", &s_useOpenGL); #endif - g_config->getOption("SDL.SpecialFilter", &s_sponge); + //g_config->getOption("SDL.SpecialFilter", &s_sponge); g_config->getOption("SDL.XStretch", &xstretch); g_config->getOption("SDL.YStretch", &ystretch); //g_config->getOption("SDL.LastXRes", &xres); @@ -188,7 +166,13 @@ InitVideo(FCEUGI *gi) g_config->getOption("SDL.ClipSides", &s_clipSides); g_config->getOption("SDL.NoFrame", &noframe); g_config->getOption("SDL.ShowFPS", &show_fps); + //g_config->getOption("SDL.XScale", &s_exs); + //g_config->getOption("SDL.YScale", &s_eys); + uint32_t rmask, gmask, bmask; + s_sponge = 0; + s_exs = 1.0; + s_eys = 1.0; xres = gtk_draw_area_width; yres = gtk_draw_area_height; // check the starting, ending, and total scan lines @@ -196,339 +180,72 @@ InitVideo(FCEUGI *gi) FCEUI_GetCurrentVidSystem(&s_srendline, &s_erendline); s_tlines = s_erendline - s_srendline + 1; - // check if we should auto-set x/y resolution + init_gui_video( s_useOpenGL ); - // check for OpenGL and set the global flags -#ifdef OPENGL - if(s_useOpenGL && !s_sponge) { - flags = SDL_OPENGL; - } -#endif - - // initialize the SDL video subsystem if it is not already active - if(!SDL_WasInit(SDL_INIT_VIDEO)) { - error = SDL_InitSubSystem(SDL_INIT_VIDEO); - if(error) { - FCEUD_PrintError(SDL_GetError()); - return -1; - } - } s_inited = 1; - // shows the cursor within the display window - SDL_ShowCursor(1); - - // determine if we can allocate the display on the video card - vinf = SDL_GetVideoInfo(); - if(vinf->hw_available) { - flags |= SDL_HWSURFACE; - } - - // get the monitor's current resolution if we do not already have it - if(s_nativeWidth < 0) { - s_nativeWidth = vinf->current_w; - } - if(s_nativeHeight < 0) { - s_nativeHeight = vinf->current_h; - } - // check to see if we are showing FPS FCEUI_SetShowFPS(show_fps); - - // check if we are rendering fullscreen - if(s_fullscreen) { - int no_cursor; - g_config->getOption("SDL.NoFullscreenCursor", &no_cursor); - flags |= SDL_FULLSCREEN; - SDL_ShowCursor(!no_cursor); - } - else { - SDL_ShowCursor(1); - } - - if(noframe) { - flags |= SDL_NOFRAME; - } - // gives the SDL exclusive palette control... ensures the requested colors - flags |= SDL_HWPALETTE; - - // enable double buffering if requested and we have hardware support -#ifdef OPENGL - if(s_useOpenGL) { - FCEU_printf("Initializing with OpenGL (Disable with '--opengl 0').\n"); - if(doublebuf) { - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - } - } else -#endif - if(doublebuf && (flags & SDL_HWSURFACE)) { - flags |= SDL_DOUBLEBUF; - } - - if(s_fullscreen) { - int desbpp, autoscale; - g_config->getOption("SDL.BitsPerPixel", &desbpp); - g_config->getOption("SDL.AutoScale", &autoscale); - if (autoscale) - { - double auto_xscale = GetXScale(xres); - double auto_yscale = GetYScale(yres); - double native_ratio = ((double)NWIDTH) / s_tlines; - double screen_ratio = ((double)xres) / yres; - int keep_ratio; - - g_config->getOption("SDL.KeepRatio", &keep_ratio); - - // Try to choose resolution - if (screen_ratio < native_ratio) - { - // The screen is narrower than the original. Maximizing width will not clip - auto_xscale = auto_yscale = GetXScale(xres); - if (keep_ratio) - auto_yscale = GetYScale(yres); - } - else - { - auto_yscale = auto_xscale = GetYScale(yres); - if (keep_ratio) - auto_xscale = GetXScale(xres); - } - s_exs = auto_xscale; - s_eys = auto_yscale; - } - else - { - g_config->getOption("SDL.XScale", &s_exs); - g_config->getOption("SDL.YScale", &s_eys); - } - g_config->getOption("SDL.SpecialFX", &s_eefx); - -#ifdef OPENGL - if(!s_useOpenGL) { - s_exs = (int)s_exs; - s_eys = (int)s_eys; - } else { - desbpp = 0; - } - - - if((s_useOpenGL && !xstretch) || !s_useOpenGL) -#endif - if(xres < (NWIDTH * s_exs) || s_exs <= 0.01) { - FCEUD_PrintError("xscale out of bounds."); - KillVideo(); - return -1; - } - -#ifdef OPENGL - if((s_useOpenGL && !ystretch) || !s_useOpenGL) -#endif - if(yres < int(s_tlines * s_eys) || s_eys <= 0.01) { - FCEUD_PrintError("yscale out of bounds."); - KillVideo(); - return -1; - } - -#ifdef OPENGL - s_screen = SDL_SetVideoMode(s_useOpenGL ? s_nativeWidth : xres, - s_useOpenGL ? s_nativeHeight : yres, - desbpp, flags); +#ifdef LSB_FIRST + rmask = 0x000000FF; + gmask = 0x0000FF00; + bmask = 0x00FF0000; #else - s_screen = SDL_SetVideoMode(xres, yres, desbpp, flags); + rmask = 0x00FF0000; + gmask = 0x0000FF00; + bmask = 0x000000FF; #endif - if(!s_screen) { - FCEUD_PrintError(SDL_GetError()); - return -1; - } - } else { - int desbpp; - g_config->getOption("SDL.BitsPerPixel", &desbpp); - - g_config->getOption("SDL.XScale", &s_exs); - g_config->getOption("SDL.YScale", &s_eys); - g_config->getOption("SDL.SpecialFX", &s_eefx); - - // -Video Modes Tag- - if(s_sponge) { - if(s_sponge <= 3 && s_sponge >= 1) - { - s_exs = s_eys = 2; - } else if (s_sponge >=4 && s_sponge <= 5) - { - s_exs = s_eys = 3; - } else if (s_sponge >= 6 && s_sponge <= 8) - { - s_exs = s_eys = s_sponge - 4; - } - else if(s_sponge == 9) - { - s_exs = s_eys = 3; - } - else - { - s_exs = s_eys = 1; - } - if(s_sponge == 3) { - xres = 301 * s_exs; - } - s_eefx = 0; - if(s_sponge == 1 || s_sponge == 4) { - desbpp = 32; - } - } - - //int scrw = NWIDTH * s_exs; - //if(s_sponge == 3) { - // scrw = 301 * s_exs; - //} - -#ifdef OPENGL - if(!s_useOpenGL) { - s_exs = (int)s_exs; - s_eys = (int)s_eys; - } - if(s_exs <= 0.01) { - FCEUD_PrintError("xscale out of bounds."); - KillVideo(); - return -1; - } - if(s_eys <= 0.01) { - FCEUD_PrintError("yscale out of bounds."); - KillVideo(); - return -1; - } - if(s_sponge && s_useOpenGL) { - FCEUD_PrintError("scalers not compatible with openGL mode."); - KillVideo(); - return -1; - } -#endif - -#if defined(_GTK) && defined(SDL_VIDEO_DRIVER_X11) && defined(GDK_WINDOWING_X11) - if(noGui == 0) - { - while (gtk_events_pending()) - gtk_main_iteration_do(FALSE); - - char SDL_windowhack[128]; - sprintf(SDL_windowhack, "SDL_WINDOWID=%u", (unsigned int)GDK_WINDOW_XID(gtk_widget_get_window(evbox))); - SDL_putenv(SDL_windowhack); - - // init SDL video - if (SDL_WasInit(SDL_INIT_VIDEO)) - SDL_QuitSubSystem(SDL_INIT_VIDEO); - if ( SDL_InitSubSystem(SDL_INIT_VIDEO) < 0 ) - { - fprintf(stderr, "Couldn't init SDL video: %s\n", SDL_GetError()); - gtk_main_quit(); - } - } -#endif - - //s_screen = SDL_SetVideoMode(scrw, (int)(s_tlines * s_eys), - s_screen = SDL_SetVideoMode( xres, yres, - desbpp, flags); - if(!s_screen) { - FCEUD_PrintError(SDL_GetError()); - return -1; - } - - // This code is not needed, gui.cpp handles all window sizing. -//#ifdef _GTK -// if(noGui == 0) -// { -// GtkRequisition req; -// gtk_widget_get_preferred_size(GTK_WIDGET(MainWindow), NULL, &req); -// gtk_window_resize(GTK_WINDOW(MainWindow), req.width, req.height); -// } -//#endif - } - if(!s_screen) { - FCEUD_PrintError(SDL_GetError()); - KillVideo(); - return -1; - } - s_curbpp = s_screen->format->BitsPerPixel; - -#if 0 - // XXX soules - this would be creating a surface on the video - // card, but was commented out for some reason... - s_BlitBuf = SDL_CreateRGBSurface(SDL_HWSURFACE, 256, 240, - s_screen->format->BitsPerPixel, - s_screen->format->Rmask, - s_screen->format->Gmask, - s_screen->format->Bmask, 0); -#endif + s_curbpp = 32; // Bits per pixel is always 32 FCEU_printf(" Video Mode: %d x %d x %d bpp %s\n", - s_screen->w, s_screen->h, s_screen->format->BitsPerPixel, + xres, yres, s_curbpp, s_fullscreen ? "full screen" : ""); - if(s_curbpp != 8 && s_curbpp != 16 && s_curbpp != 24 && s_curbpp != 32) { + if (s_curbpp != 8 && s_curbpp != 16 && s_curbpp != 24 && s_curbpp != 32) + { FCEU_printf(" Sorry, %dbpp modes are not supported by FCE Ultra. Supported bit depths are 8bpp, 16bpp, and 32bpp.\n", s_curbpp); KillVideo(); return -1; } - // if the game being run has a name, set it as the window name - if(gi) - { - if(gi->name) { - SDL_WM_SetCaption((const char *)gi->name, (const char *)gi->name); - } else { - SDL_WM_SetCaption(FCEU_NAME_AND_VERSION,"FCE Ultra"); - } - } - - // create the surface for displaying graphical messages -#ifdef LSB_FIRST - s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data, - 32, 32, 24, 32 * 3, - 0xFF, 0xFF00, 0xFF0000, 0x00); -#else - s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data, - 32, 32, 24, 32 * 3, - 0xFF0000, 0xFF00, 0xFF, 0x00); -#endif - SDL_WM_SetIcon(s_IconSurface,0); - s_paletterefresh = 1; - - // XXX soules - can't SDL do this for us? - // if using more than 8bpp, initialize the conversion routines - if(s_curbpp > 8) { - InitBlitToHigh(s_curbpp >> 3, - s_screen->format->Rmask, - s_screen->format->Gmask, - s_screen->format->Bmask, - s_eefx, s_sponge, 0); #ifdef OPENGL - if(s_useOpenGL) - { - int openGLip; - g_config->getOption("SDL.OpenGLip", &openGLip); - - if(!InitOpenGL(NOFFSET, 256 - (s_clipSides ? 8 : 0), - s_srendline, s_erendline + 1, - s_exs, s_eys, s_eefx, - openGLip, xstretch, ystretch, s_screen)) - { - FCEUD_PrintError("Error initializing OpenGL."); - KillVideo(); - return -1; - } - } -#endif + if(s_exs <= 0.01) { + FCEUD_PrintError("xscale out of bounds."); + KillVideo(); + return -1; } + if(s_eys <= 0.01) { + FCEUD_PrintError("yscale out of bounds."); + KillVideo(); + return -1; + } + if(s_sponge && s_useOpenGL) { + FCEUD_PrintError("scalers not compatible with openGL mode."); + KillVideo(); + return -1; + } +#endif + + if ( !initBlitToHighDone ) + { + InitBlitToHigh(s_curbpp >> 3, + rmask, + gmask, + bmask, + s_eefx, s_sponge, 0); + + initBlitToHighDone = 1; + } + return 0; } -#endif /** * Toggles the full-screen display. */ -void ToggleFS() +void ToggleFS(void) { // pause while we we are making the switch bool paused = FCEUI_EmulationPaused(); @@ -600,23 +317,10 @@ FCEUD_GetPalette(uint8 index, */ static void RedoPalette() { -#ifdef OPENGL - if(s_useOpenGL) - SetOpenGLPalette((uint8*)s_psdl); - else -#endif + if (s_curbpp > 8) { - if(s_curbpp > 8) { - SetPaletteBlitToHigh((uint8*)s_psdl); - } else - { -#if SDL_VERSION_ATLEAST(2, 0, 0) - //TODO - SDL2 -#else - SDL_SetPalette(s_screen, SDL_PHYSPAL, s_psdl, 0, 256); -#endif - } - } + SetPaletteBlitToHigh((uint8*)s_psdl); + } } // XXX soules - console lock/unlock unimplemented? @@ -632,126 +336,32 @@ void UnlockConsole(){} void BlitScreen(uint8 *XBuf) { - SDL_Surface *TmpScreen; uint8 *dest; - int xo = 0, yo = 0; - - if(!s_screen) { - return; - } + int w, h, pitch; // refresh the palette if required - if(s_paletterefresh) { + if (s_paletterefresh) + { RedoPalette(); s_paletterefresh = 0; } -#ifdef OPENGL - // OpenGL is handled separately - if(s_useOpenGL) { - BlitOpenGL(XBuf); - return; - } -#endif - // XXX soules - not entirely sure why this is being done yet XBuf += s_srendline * 256; - if(s_BlitBuf) { - TmpScreen = s_BlitBuf; - } else { - TmpScreen = s_screen; - } + dest = (uint8*)getGuiPixelBuffer( &w, &h, &pitch ); - // lock the display, if necessary - if(SDL_MUSTLOCK(TmpScreen)) { - if(SDL_LockSurface(TmpScreen) < 0) { - return; - } - } + glx_shm->ncol = NWIDTH; + glx_shm->nrow = s_tlines; + glx_shm->pitch = pitch; - dest = (uint8*)TmpScreen->pixels; + if ( dest == NULL ) return; - //if(s_fullscreen) { // Always do this calculation now. Screen resolution is always provided. - xo = (int)(((TmpScreen->w - NWIDTH * s_exs)) / 2); - dest += xo * (s_curbpp >> 3); - if(TmpScreen->h > (s_tlines * s_eys)) { - yo = (int)((TmpScreen->h - s_tlines * s_eys) / 2); - dest += yo * TmpScreen->pitch; - } - //} + Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, pitch, 1, 1); - // XXX soules - again, I'm surprised SDL can't handle this - // perform the blit, converting bpp if necessary - if(s_curbpp > 8) { - if(s_BlitBuf) { - Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, - TmpScreen->pitch, 1, 1); - } else { - Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines, - TmpScreen->pitch, (int)s_exs, (int)s_eys); - } - } else { - if(s_BlitBuf) { - Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines, - TmpScreen->pitch, 1, 1, 0, s_sponge); - } else { - Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines, - TmpScreen->pitch, (int)s_exs, (int)s_eys, - s_eefx, s_sponge); - } - } - - // unlock the display, if necessary - if(SDL_MUSTLOCK(TmpScreen)) { - SDL_UnlockSurface(TmpScreen); - } - - int scrw; - if(s_sponge == 3) { // NTSC 2x - scrw = 301; - } else { - scrw = NWIDTH; - } - - // if we have a hardware video buffer, do a fast video->video copy - if(s_BlitBuf) { - SDL_Rect srect; - SDL_Rect drect; - - srect.x = 0; - srect.y = 0; - srect.w = scrw; - srect.h = s_tlines; - - drect.x = 0; - drect.y = 0; - drect.w = (Uint16)(s_exs * scrw); - drect.h = (Uint16)(s_eys * s_tlines); - - SDL_BlitSurface(s_BlitBuf, &srect, s_screen, &drect); - } - - // ensure that the display is updated -#if SDL_VERSION_ATLEAST(2, 0, 0) - //TODO - SDL2 -#else - SDL_UpdateRect(s_screen, xo, yo, - (Uint32)(scrw * s_exs), (Uint32)(s_tlines * s_eys)); -#endif + guiPixelBufferReDraw(); #ifdef CREATE_AVI -#if 0 /* PAL INTO NTSC HACK */ - { int fps = FCEUI_GetDesiredFPS(); - if(FCEUI_GetDesiredFPS() == 838977920) fps = 1008307711; - NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); - if(FCEUI_GetDesiredFPS() == 838977920) - { - static unsigned dup=0; - if(++dup==5) { dup=0; - NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); } - } } -#else { int fps = FCEUI_GetDesiredFPS(); static unsigned char* result = NULL; static unsigned resultsize = 0; @@ -781,10 +391,10 @@ BlitScreen(uint8 *XBuf) break; #endif default: - NESVideoLoggingVideo(s_screen->pixels, width,height, fps, s_curbpp); + NESVideoLoggingVideo( dest, width,height, fps, s_curbpp); } } -#endif +#endif // CREATE_AVI #if REALTIME_LOGGING { @@ -811,17 +421,8 @@ BlitScreen(uint8 *XBuf) } memcpy(&last_time, &cur_time, sizeof(last_time)); } -#endif -#endif +#endif // REALTIME_LOGGING -#if SDL_VERSION_ATLEAST(2, 0, 0) - // TODO -#else - // have to flip the displayed buffer in the case of double buffering - if(s_screen->flags & SDL_DOUBLEBUF) { - SDL_Flip(s_screen); - } -#endif } /** diff --git a/src/drivers/sdl/sdl.cpp b/src/drivers/sdl/sdl.cpp index a2c00cda..fb421832 100644 --- a/src/drivers/sdl/sdl.cpp +++ b/src/drivers/sdl/sdl.cpp @@ -16,6 +16,7 @@ #include "sdl.h" #include "sdl-video.h" #include "unix-netplay.h" +#include "glxwin.h" #include "../common/configSys.h" #include "../../oldmovie.h" @@ -171,13 +172,9 @@ static void ShowUsage(char *prog) #endif puts(""); printf("Compiled with SDL version %d.%d.%d\n", SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL ); -#if SDL_VERSION_ATLEAST(2, 0, 0) - SDL_version* v; - SDL_GetVersion(v); -#else - const SDL_version* v = SDL_Linked_Version(); -#endif - printf("Linked with SDL version %d.%d.%d\n", v->major, v->minor, v->patch); + SDL_version v; + SDL_GetVersion(&v); + printf("Linked with SDL version %d.%d.%d\n", v.major, v.minor, v.patch); #ifdef GTK printf("Compiled with GTK version %d.%d.%d\n", GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION ); //printf("Linked with GTK version %d.%d.%d\n", GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION ); @@ -560,9 +557,9 @@ int main(int argc, char *argv[]) return(-1); } -#ifdef OPENGL - SDL_GL_LoadLibrary(0); -#endif +//#ifdef OPENGL +// SDL_GL_LoadLibrary(0); +//#endif // Initialize the configuration system g_config = InitConfig(); @@ -679,41 +676,6 @@ int main(int argc, char *argv[]) int yres, xres; g_config->getOption("SDL.XResolution", &xres); g_config->getOption("SDL.YResolution", &yres); -#if SDL_VERSION_ATLEAST(2, 0, 0) - // TODO _ SDL 2.0 -#else - const SDL_VideoInfo* vid_info = SDL_GetVideoInfo(); - if(xres == 0) - { - if(vid_info != NULL) - { - g_config->setOption("SDL.LastXRes", vid_info->current_w); - } - else - { - g_config->setOption("SDL.LastXRes", 512); - } - } - else - { - g_config->setOption("SDL.LastXRes", xres); - } - if(yres == 0) - { - if(vid_info != NULL) - { - g_config->setOption("SDL.LastYRes", vid_info->current_h); - } - else - { - g_config->setOption("SDL.LastYRes", 448); - } - } - else - { - g_config->setOption("SDL.LastYRes", yres); - } -#endif int autoResume; g_config->getOption("SDL.AutoResume", &autoResume); @@ -857,6 +819,7 @@ int main(int argc, char *argv[]) #ifdef _GTK if(noGui == 0) { + spawn_glxwin(0); // even though it is not spawning a window, still needed for shared memory segment. gtk_init(&argc, &argv); InitGTKSubsystem(argc, argv); while(gtk_events_pending()) @@ -948,11 +911,18 @@ int main(int argc, char *argv[]) while(1) { if(GameInfo) + { DoFun(frameskip, periodic_saves); + } else + { SDL_Delay(1); + } + while(gtk_events_pending()) - gtk_main_iteration_do(FALSE); + { + gtk_main_iteration_do(FALSE); + } } } else