--- uae/src/sdlgfx.c 2018/04/24 17:14:08 1.1.1.3 +++ uae/src/sdlgfx.c 2018/04/24 17:16:21 1.1.1.4 @@ -1,9 +1,10 @@ /* * UAE - The Un*x Amiga Emulator * - * SDL interface + * SDL graphics support * * Copyright 2001 Bernd Lachner (EMail: dev@lachner-net.de) + * Copyright 2003-2006 Richard Drummond * * Partialy based on the UAE X interface (xwin.c) * @@ -17,711 +18,634 @@ #include "sysconfig.h" #include "sysdeps.h" -#include #include +#include +#include -#include -#include - -#include "config.h" #include "options.h" #include "uae.h" -#include "memory.h" #include "xwin.h" #include "custom.h" #include "drawing.h" -#include "newcpu.h" #include "keyboard.h" #include "keybuf.h" #include "gui.h" #include "debug.h" #include "picasso96.h" +#include "inputdevice.h" +#include "hotkeys.h" +#include "sdlgfx.h" /* Uncomment for debugging output */ -/* #define DEBUG */ - -#ifdef __cplusplus -static RETSIGTYPE sigbrkhandler(...) +//#define DEBUG +#ifdef DEBUG +#define DEBUG_LOG write_log #else -static RETSIGTYPE sigbrkhandler (int foo) -#endif -{ - activate_debugger(); -#if !defined(__unix) || defined(__NeXT__) - signal (SIGINT, sigbrkhandler); +#define DEBUG_LOG(...) do ; while(0) #endif -} -void setup_brkhandler (void) -{ -#if defined(__unix) && !defined(__NeXT__) - struct sigaction sa; - sa.sa_handler = sigbrkhandler; - sa.sa_flags = 0; -#ifdef SA_RESTART - sa.sa_flags = SA_RESTART; -#endif - sigemptyset (&sa.sa_mask); - sigaction (SIGINT, &sa, NULL); -#else - signal (SIGINT, sigbrkhandler); -#endif -} +static SDL_Surface *display; +static SDL_Surface *screen; -/* SDL variable for output surface */ -static SDL_Surface *prSDLScreen = NULL; -/* Possible screen modes (x and y resolutions) */ -#define MAX_SCREEN_MODES 11 +/* Standard P96 screen modes */ +#define MAX_SCREEN_MODES 12 static int x_size_table[MAX_SCREEN_MODES] = { 320, 320, 320, 320, 640, 640, 640, 800, 1024, 1152, 1280 }; -static int y_size_table[MAX_SCREEN_MODES] = { 200, 240, 256, 400, 350, 480, 512, 600, 768, 864, 1024 }; -/* Possible screen depth (0 terminated) */ -static int aScreenDepth[] = {16, 15, 12, 0}; +static int y_size_table[MAX_SCREEN_MODES] = { 200, 240, 256, 400, 350, 480, 512, 600, 768, 864, 1024 }; + +/* Supported SDL screen modes */ +#define MAX_SDL_SCREENMODE 32 +SDL_Rect screenmode[MAX_SDL_SCREENMODE]; +int mode_count; + +static int sdlgfx_init_ok; static int red_bits, green_bits, blue_bits; static int red_shift, green_shift, blue_shift; +#ifdef PICASSO96 static int screen_is_picasso; static char picasso_invalid_lines[1201]; static int picasso_has_invalid_lines; static int picasso_invalid_start, picasso_invalid_stop; static int picasso_maxw = 0, picasso_maxh = 0; +#endif static int bitdepth, bit_unit; - static int current_width, current_height; -static SDL_Color arSDLColors[256]; -static int ncolors = 0; -/* Keyboard and mouse */ -static int keystate[256]; +/* If we have to lock the SDL surface, then we remember the address + * of its pixel data - and recalculate the row maps only when this + * address changes */ +static void *old_pixels; -static void handle_mousegrab(void); -static void handle_inhibit(void); -static void framerate_up(void); -static void framerate_down(void); -static void togglefullscreen(void) -{ - SDL_WM_ToggleFullScreen(prSDLScreen); -}; +static SDL_Color arSDLColors[256]; +#ifdef PICASSO96 +static SDL_Color p96Colors[256]; +#endif +static int ncolors; -static void handle_interpol (void); +static int fullscreen; +static int mousegrab; -struct SDLHotKey -{ - SDLKey aHotKeys[2]; - void (*pfHandler)(void); - long aPressedKeys[2]; -}; +static int is_hwsurface; +static int have_rawkeys; -static struct SDLHotKey arHotKeys[] = -{ - {{ SDLK_F12, SDLK_s}, togglefullscreen, {0, 0} }, - {{ SDLK_F12, SDLK_q}, uae_quit, {0, 0} }, - {{ SDLK_F12, SDLK_m}, togglemouse, {0, 0} }, - {{ SDLK_F12, SDLK_g}, handle_mousegrab, {0, 0} }, - {{ SDLK_F12, SDLK_i}, handle_inhibit, {0, 0} }, - {{ SDLK_F12, SDLK_p}, handle_interpol, {0, 0} }, - {{ SDLK_F12, SDLK_KP_PLUS}, framerate_up, {0, 0} }, - {{ SDLK_F12, SDLK_KP_MINUS}, framerate_down, {0, 0} }, - {{ 0, 0 }, NULL, {0, 0} } /* List must be terminated */ -}; +/* This isn't supported yet. + * gui_handle_events() needs to be reworked fist + */ +int pause_emulation; -void flush_line (int y) +#ifdef __cplusplus +static RETSIGTYPE sigbrkhandler(...) +#else +static RETSIGTYPE sigbrkhandler (int foo) +#endif { - /* Not implemented for SDL output */ -#ifdef DEBUG - fprintf(stderr, "Function: flush_line\n"); + activate_debugger(); +#if !defined(__unix) || defined(__NeXT__) + signal (SIGINT, sigbrkhandler); #endif } -void flush_block (int ystart, int ystop) +void setup_brkhandler (void) { -#ifdef DEBUG - fprintf(stderr, "Function: flush_block %d %d\n", ystart, ystop); +#if defined(__unix) && !defined(__NeXT__) + struct sigaction sa; + sa.sa_handler = sigbrkhandler; + sa.sa_flags = 0; +#ifdef SA_RESTART + sa.sa_flags = SA_RESTART; +#endif + sigemptyset (&sa.sa_mask); + sigaction (SIGINT, &sa, NULL); +#else + signal (SIGINT, sigbrkhandler); #endif - SDL_UnlockSurface (prSDLScreen); - SDL_UpdateRect(prSDLScreen, 0, ystart, current_width, ystop-ystart+1); - SDL_LockSurface (prSDLScreen); } -void flush_screen (int ystart, int ystop) -{ -#ifdef DEBUG - fprintf(stderr, "Function: flush_screen\n"); -#endif +/* + * What graphics platform are we running on . . .? + * + * Yes, SDL is supposed to abstract away from the underlying + * platform, but we need to know this to be able to map raw keys + * and to work around any platform-specific quirks . . . + */ +int get_sdlgfx_type (void) +{ + char name[16] = ""; + static int driver = SDLGFX_DRIVER_UNKNOWN; + static int search_done = 0; + + if (!search_done) { + if (SDL_VideoDriverName (name, sizeof name)) { + if (strcmp (name, "x11")==0) + driver = SDLGFX_DRIVER_X11; + else if (strcmp (name, "dga") == 0) + driver = SDLGFX_DRIVER_DGA; + else if (strcmp (name, "svgalib") == 0) + driver = SDLGFX_DRIVER_SVGALIB; + else if (strcmp (name, "fbcon") == 0) + driver = SDLGFX_DRIVER_FBCON; + else if (strcmp (name, "directfb") == 0) + driver = SDLGFX_DRIVER_DIRECTFB; + else if (strcmp (name, "Quartz") == 0) + driver = SDLGFX_DRIVER_QUARTZ; + else if (strcmp (name, "bwindow") == 0) + driver = SDLGFX_DRIVER_BWINDOW; + else if (strcmp (name, "CGX") == 0) + driver = SDLGFX_DRIVER_CYBERGFX; + else if (strcmp (name, "OS4") == 0) + driver = SDLGFX_DRIVER_AMIGAOS4; + } + search_done = 1; -#if 0 - SDL_UpdateRect(prSDLScreen, 0, 0, current_width, current_height); -#endif + DEBUG_LOG ("SDL video driver: %s\n", name); + } + return driver; } -STATIC_INLINE int bitsInMask (unsigned long mask) +STATIC_INLINE unsigned long bitsInMask (unsigned long mask) { - /* count bits in mask */ - int n = 0; - while (mask) - { - n += mask & 1; - mask >>= 1; - } - return n; + /* count bits in mask */ + unsigned long n = 0; + while (mask) { + n += mask & 1; + mask >>= 1; + } + return n; } -STATIC_INLINE int maskShift (unsigned long mask) +STATIC_INLINE unsigned long maskShift (unsigned long mask) { - /* determine how far mask is shifted */ - int n = 0; - while (!(mask & 1)) - { - n++; - mask >>= 1; - } - return n; + /* determine how far mask is shifted */ + unsigned long n = 0; + while (!(mask & 1)) { + n++; + mask >>= 1; + } + return n; } static int get_color (int r, int g, int b, xcolnr *cnp) { -#ifdef DEBUG - fprintf(stderr, "Function: get_color\n"); -#endif - - *cnp = SDL_MapRGB(prSDLScreen->format, r, g, b); - arSDLColors[ncolors].r = r; - arSDLColors[ncolors].g = g; - arSDLColors[ncolors].b = b; + DEBUG_LOG ("Function: get_color\n"); - ncolors++; - return 1; + arSDLColors[ncolors].r = r << 4; + arSDLColors[ncolors].g = g << 4; + arSDLColors[ncolors].b = b << 4; + *cnp = ncolors++; + return 1; } static int init_colors (void) { - int i; + int i; -#ifdef DEBUG - fprintf(stderr, "Function: init_colors\n"); -#endif + DEBUG_LOG ("Function: init_colors\n"); - if (bitdepth > 8) - { - /* Truecolor: */ - red_bits = bitsInMask(prSDLScreen->format->Rmask); - green_bits = bitsInMask(prSDLScreen->format->Gmask); - blue_bits = bitsInMask(prSDLScreen->format->Bmask); - red_shift = maskShift(prSDLScreen->format->Rmask); - green_shift = maskShift(prSDLScreen->format->Gmask); - blue_shift = maskShift(prSDLScreen->format->Bmask); - alloc_colors64k (red_bits, green_bits, blue_bits, red_shift, green_shift, blue_shift); - } - else - { - alloc_colors256 (get_color); - SDL_SetColors(prSDLScreen, arSDLColors, 0, 256); - } + if (bitdepth > 8) { + red_bits = bitsInMask (display->format->Rmask); + green_bits = bitsInMask (display->format->Gmask); + blue_bits = bitsInMask (display->format->Bmask); + red_shift = maskShift (display->format->Rmask); + green_shift = maskShift (display->format->Gmask); + blue_shift = maskShift (display->format->Bmask); + + alloc_colors64k (red_bits, green_bits, blue_bits, red_shift, green_shift, blue_shift); + } else { + alloc_colors256 (get_color); + SDL_SetColors (screen, arSDLColors, 0, 256); + } - switch (gfxvidinfo.pixbytes) - { - case 2: - for (i = 0; i < 4096; i++) - xcolors[i] = xcolors[i] * 0x00010001; - gfxvidinfo.can_double = 1; - break; - case 1: - for (i = 0; i < 4096; i++) - xcolors[i] = xcolors[i] * 0x01010101; - gfxvidinfo.can_double = 1; - break; - default: - gfxvidinfo.can_double = 0; + return 1; +} + + +/* + * Test whether the screen mode xx is + * available. If not, find a supported screen mode which best + * matches. + */ +static int find_best_mode (int *width, int *height, int depth, int *try_fs) +{ + int found = 0; + + DEBUG_LOG ("Function: find_best_mode(%d,%d,%d)\n", *width, *height, depth); + + restart: + /* First test whether the specified mode is supported */ + found = SDL_VideoModeOK (*width, *height, depth, *try_fs ? SDL_FULLSCREEN : 0); + + if (!found && mode_count > 0) { + /* The specified mode wasn't available, so we'll try and find + * a supported resolution which best matches it. + */ + int i; + write_log ("SDLGFX: Requested mode (%dx%d%d) not available.\n", *width, *height, depth); + + /* Note: the screenmode array should already be sorted from largest to smallest, since + * that's the order SDL gives us the screenmodes. */ + for (i = mode_count - 1; i >= 0; i--) { + if (screenmode[i].w >= *width && screenmode[i].h >= *height) break; } - if (SDL_BYTEORDER == SDL_BIG_ENDIAN) - { - switch (gfxvidinfo.pixbytes) - { - case 4: - for(i = 0; i < 4096; i++) - SDL_Swap32(xcolors[i]); - break; - case 2: - for (i = 0; i < 4096; i++) - SDL_Swap16(xcolors[i]); - break; - } + + /* If we didn't find a mode, use the largest supported mode */ + if (i < 0) + i = 0; + + *width = screenmode[i].w; + *height = screenmode[i].h; + found = 1; + + write_log ("SDLGFX: Using mode (%dx%d)\n", *width, *height); + } + if (!found && *try_fs) { + *try_fs = 0; + goto restart; + } + return found; +} + +#ifdef PICASSO96 +/* + * Map an SDL pixel format to a P96 pixel format + */ +static int get_p96_pixel_format (const struct SDL_PixelFormat *fmt) +{ + if (fmt->BitsPerPixel == 8) + return RGBFB_CLUT; + +#ifdef WORDS_BIGENDIAN + if (fmt->BitsPerPixel == 24) { + if (fmt->Rmask == 0x00FF0000 && fmt->Gmask == 0x0000FF00 && fmt->Bmask == 0x000000FF) + return RGBFB_R8G8B8; + if (fmt->Rmask == 0x000000FF && fmt->Gmask == 0x0000FF00 && fmt->Bmask == 0x00FF0000) + return RGBFB_B8G8R8; + } else if (fmt->BitsPerPixel == 32) { + if (fmt->Rmask == 0xFF000000 && fmt->Gmask == 0x00FF0000 && fmt->Bmask == 0x0000FF00) + return RGBFB_R8G8B8A8; + if (fmt->Rmask == 0x00FF0000 && fmt->Gmask == 0x0000FF00 && fmt->Bmask == 0x000000FF) + return RGBFB_A8R8G8B8; + if (fmt->Bmask == 0x00FF0000 && fmt->Gmask == 0x0000FF00 && fmt->Rmask == 0x000000FF) + return RGBFB_A8B8G8R8; + if (fmt->Bmask == 0xFF000000 && fmt->Gmask == 0x00FF0000 && fmt->Rmask == 0x0000FF00) + return RGBFB_B8G8R8A8; + } else if (fmt->BitsPerPixel == 16) { + if (get_sdlgfx_type () == SDLGFX_DRIVER_QUARTZ) { + /* The MacOS X port of SDL lies about it's default pixel format + * for high-colour display. It's always R5G5B5. */ + return RGBFB_R5G5B5; + } else { + if (fmt->Rmask == 0xf800 && fmt->Gmask == 0x07e0 && fmt->Bmask == 0x001f) + return RGBFB_R5G6B5; + if (fmt->Rmask == 0x7C00 && fmt->Gmask == 0x03e0 && fmt->Bmask == 0x001f) + return RGBFB_R5G5B5; } - return 1; + } else if (fmt->BitsPerPixel == 15) { + if (fmt->Rmask == 0x7C00 && fmt->Gmask == 0x03e0 && fmt->Bmask == 0x001f) + return RGBFB_R5G5B5; + } +#else + if (fmt->BitsPerPixel == 24) { + if (fmt->Rmask == 0x00FF0000 && fmt->Gmask == 0x0000FF00 && fmt->Bmask == 0x000000FF) + return RGBFB_B8G8R8; + if (fmt->Rmask == 0x000000FF && fmt->Gmask == 0x0000FF00 && fmt->Bmask == 0x00FF0000) + return RGBFB_R8G8B8; + } else if (fmt->BitsPerPixel == 32) { + if (fmt->Rmask == 0xFF000000 && fmt->Gmask == 0x00FF0000 && fmt->Bmask == 0x0000FF00) + return RGBFB_A8B8G8R8; + if (fmt->Rmask == 0x00FF0000 && fmt->Gmask == 0x0000FF00 && fmt->Bmask == 0x000000FF) + return RGBFB_B8G8R8A8; + if (fmt->Bmask == 0x00FF0000 && fmt->Gmask == 0x0000FF00 && fmt->Rmask == 0x000000FF) + return RGBFB_R8G8B8A8; + if (fmt->Bmask == 0xFF000000 && fmt->Gmask == 0x00FF0000 && fmt->Rmask == 0x0000FF00) + return RGBFB_A8R8G8B8; + } else if (fmt->BitsPerPixel == 16) { + if (fmt->Rmask == 0xf800 && fmt->Gmask == 0x07e0 && fmt->Bmask == 0x001f) + return RGBFB_R5G6B5PC; + if (fmt->Rmask == 0x7C00 && fmt->Gmask == 0x03e0 && fmt->Bmask == 0x001f) + return RGBFB_R5G5B5PC; + } else if (fmt->BitsPerPixel == 15) { + if (fmt->Rmask == 0x7C00 && fmt->Gmask == 0x03e0 && fmt->Bmask == 0x001f) + return RGBFB_R5G5B5PC; + } +#endif + + return RGBFB_NONE; } +#endif -int graphics_setup (void) +/* + * Build list of full-screen screen-modes supported by SDL + * with the specified pixel format. + * + * Returns a count of the number of supported modes, -1 if any mode is supported, + * or 0 if there are no modes with this pixel format. + */ +static long find_screen_modes (struct SDL_PixelFormat *vfmt, SDL_Rect *mode_list, int mode_list_size) +{ + long count = 0; + SDL_Rect **modes = SDL_ListModes (vfmt, SDL_FULLSCREEN | SDL_HWSURFACE); + + if (modes != 0 && modes != (SDL_Rect**)-1) { + unsigned int i; + int w = -1; + int h = -1; + + /* Filter list of modes SDL gave us and ignore duplicates */ + for (i = 0; modes[i] && count < mode_list_size; i++) { + if (modes[i]->w != w || modes[i]->h != h) { + mode_list[count].w = w = modes[i]->w; + mode_list[count].h = h = modes[i]->h; + count++; + + write_log ("SDLGFX: Found screenmode: %dx%d.\n", w, h); + } + } + } else + count = (long) modes; + + return count; +} + +/** + ** Buffer methods for SDL surfaces that must be locked + **/ + +int lockscr (void) { -#ifdef DEBUG - fprintf(stderr, "Function: graphics_setup\n"); -#endif + int success = 0; - /* Initialize the SDL library */ - if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) - { - fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); - return 0; + if (!SDL_MUSTLOCK (screen)) + return 1; + + if (SDL_LockSurface (display) == 0) { + gfxvidinfo.bufmem = display->pixels; + gfxvidinfo.rowbytes = display->pitch; + + if (display->pixels != old_pixels) { + /* If the address of the pixel data has + * changed, recalculate the row maps + */ + init_row_map (); + old_pixels = display->pixels; + } + success = 1; } + return success; +} - return 1; +void unlockscr (void) +{ + if (SDL_MUSTLOCK (screen)) + SDL_UnlockSurface (display); } +void flush_block (int first_line, int last_line) +{ + // DEBUG_LOG ("Function: flush_block %d %d\n", first_line, last_line); + + SDL_UpdateRect (display, 0, first_line, current_width, last_line - first_line + 1); +} -static void graphics_subinit (void) +void flush_screen (int first_line, int last_line) { - Uint32 uiSDLVidModFlags; + if (! (screen->flags & SDL_DOUBLEBUF)) + return; -#ifdef DEBUG - fprintf(stderr, "Function: graphics_subinit\n"); -#endif + SDL_BlitSurface (display,0,screen,0); - /* Open SDL Window in current mode */ - uiSDLVidModFlags = SDL_SWSURFACE; - if (bitdepth == 8) - { - uiSDLVidModFlags |= SDL_HWPALETTE; - } - if (currprefs.gfx_afullscreen || currprefs.gfx_pfullscreen) - { - uiSDLVidModFlags |= SDL_FULLSCREEN; - } - fprintf(stderr, "Resolution: %d x %d x %d\n", current_width, current_height, bitdepth); + SDL_Flip (screen); +} - prSDLScreen = SDL_SetVideoMode(current_width, current_height, bitdepth, uiSDLVidModFlags); - if (prSDLScreen == NULL) - { - fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError()); - return; - } - else - { -#ifdef DEBUG - fprintf(stderr, "Bytes per Pixel: %d\n", prSDLScreen->format->BytesPerPixel); - fprintf(stderr, "Bytes per Line: %d\n", prSDLScreen->pitch); -#endif - SDL_LockSurface(prSDLScreen); - memset(prSDLScreen->pixels, 0, current_width * current_height * prSDLScreen->format->BytesPerPixel); - SDL_UnlockSurface(prSDLScreen); - SDL_UpdateRect(prSDLScreen, 0, 0, current_width, current_height); - /* Set UAE window title and icon name */ - SDL_WM_SetCaption("UAE","UAE"); - /* Hide mouse cursor */ - SDL_ShowCursor(SDL_DISABLE); - /* Initialize structure for Amiga video modes */ - gfxvidinfo.bufmem = prSDLScreen->pixels; - gfxvidinfo.linemem = 0; - gfxvidinfo.emergmem = 0; - gfxvidinfo.pixbytes = prSDLScreen->format->BytesPerPixel; - bit_unit = prSDLScreen->format->BytesPerPixel * 8; - gfxvidinfo.rowbytes = prSDLScreen->pitch; - gfxvidinfo.maxblocklines = 100; - gfxvidinfo.can_double = 0; - /* Initialize structure for Picasso96 video modes */ - picasso_vidinfo.rowbytes = current_width * gfxvidinfo.pixbytes; - picasso_vidinfo.extra_mem = 1; - picasso_vidinfo.depth = bitdepth; - picasso_has_invalid_lines = 0; - picasso_invalid_start = picasso_vidinfo.height + 1; - picasso_invalid_stop = -1; - memset (picasso_invalid_lines, 0, sizeof picasso_invalid_lines); - } - lastmx = lastmy = 0; - newmousecounters = 0; +void flush_line (int line) +{ } +int graphics_setup (void) +{ + int result = 0; -int graphics_init (void) + if (SDL_InitSubSystem (SDL_INIT_VIDEO) == 0) { + + const SDL_version *version = SDL_Linked_Version (); + const SDL_VideoInfo *info = SDL_GetVideoInfo (); + + write_log ("SDLGFX: Initialized.\n"); + write_log ("SDLGFX: Using SDL version %d.%d.%d.\n", version->major, version->minor, version->patch); + + /* Find default display depth */ + bitdepth = info->vfmt->BitsPerPixel; + bit_unit = info->vfmt->BytesPerPixel * 8; + + write_log ("SDLGFX: Display is %d bits deep.\n", bitdepth); + + /* Build list of screenmodes */ + mode_count = find_screen_modes (info->vfmt, &screenmode[0], MAX_SDL_SCREENMODE); + + result = 1; + sdlgfx_init_ok = 1; + } else + write_log ("SDLGFX: initialization failed - %s\n", SDL_GetError()); + + return result; +} + +static int graphics_subinit (void) { - int i,j; + Uint32 uiSDLVidModFlags = 0; -#ifdef DEBUG - fprintf(stderr, "Function: graphics_init\n"); -#endif + DEBUG_LOG ("Function: graphics_subinit\n"); - if (currprefs.color_mode > 5) - fprintf (stderr, "Bad color mode selected. Using default.\n"), currprefs.color_mode = 0; + if (screen_is_picasso) { + // Set height, width for Picasso gfx + current_width = picasso_vidinfo.width; + current_height = picasso_vidinfo.height; + fullscreen = currprefs.gfx_pfullscreen; + curr_gfx = 0; + } else { + // Set height, width for Amiga gfx + fullscreen = currprefs.gfx_afullscreen; + if (fullscreen) + curr_gfx = &currprefs.gfx_f; + else + curr_gfx = &currprefs.gfx_w; + + current_width = curr_gfx->width; + current_height = curr_gfx->height; + } + find_best_mode (¤t_width, ¤t_height, bitdepth, &fullscreen); + if (!screen_is_picasso) { + gfxvidinfo.width = current_width; + gfxvidinfo.height = current_height; + } - screen_is_picasso = 0; + if (bitdepth == 8) + uiSDLVidModFlags |= SDL_HWPALETTE; + if (fullscreen) { + uiSDLVidModFlags |= SDL_FULLSCREEN | SDL_HWSURFACE; + if(!screen_is_picasso && 0 /*currprefs.gfx_vsync */) + uiSDLVidModFlags |= SDL_DOUBLEBUF; + } - fixup_prefs_dimensions (&currprefs); + DEBUG_LOG ("Resolution: %d x %d x %d (FS: %d)\n", current_width, current_height, bitdepth, fullscreen); + screen = SDL_SetVideoMode (current_width, current_height, bitdepth, uiSDLVidModFlags); - gfxvidinfo.width = currprefs.gfx_width; - gfxvidinfo.height = currprefs.gfx_height; - current_width = currprefs.gfx_width; - current_height = currprefs.gfx_height; + if (screen == NULL) { +#if 0 + gui_message ("Unable to set video mode: %s\n", SDL_GetError ()); +#endif + return 0; + } else { + /* Just in case we didn't get exactly what we asked for . . . */ + fullscreen = ((screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN); + is_hwsurface = ((screen->flags & SDL_HWSURFACE) == SDL_HWSURFACE); + + /* Are these values what we expected? */ +# ifdef PICASSO96 + DEBUG_LOG ("P96 screen? : %d\n", screen_is_picasso); +# endif + DEBUG_LOG ("Fullscreen? : %d\n", fullscreen); + DEBUG_LOG ("Mouse grabbed? : %d\n", mousegrab); + DEBUG_LOG ("HW surface? : %d\n", is_hwsurface); + DEBUG_LOG ("Must lock? : %d\n", SDL_MUSTLOCK (screen)); + DEBUG_LOG ("Bytes per Pixel: %d\n", screen->format->BytesPerPixel); + DEBUG_LOG ("Bytes per Line : %d\n", screen->pitch); + + /* Set up buffer methods */ + + if (screen->flags & SDL_DOUBLEBUF) { + display = SDL_CreateRGBSurface(SDL_HWSURFACE, screen->w, screen->h, screen->format->BitsPerPixel, + screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, 0); - /* Find a SDL video mode with exact width and height */ - for (i = 0; aScreenDepth[i] != 0; i++) - { - bitdepth = SDL_VideoModeOK(current_width, current_height, aScreenDepth[i], SDL_SWSURFACE); - if (bitdepth) - { - #ifdef DEBUG - fprintf(stderr, "Bit depth: %d\n", bitdepth); - #endif - break; - } - else - { - fprintf(stderr, "Video mode %dx%d@%d not available\n", current_width, current_height, aScreenDepth[i]); - } - } - if (bitdepth == 0) - { - /* Find a SDL video mode from standard resolutions */ - for (j = 0; j < MAX_SCREEN_MODES && !bitdepth; j++) - { - if (x_size_table[j] < current_width || y_size_table[j] < current_height) - continue; - for (i = 0; aScreenDepth[i] != 0 && !bitdepth; i++) - { - bitdepth = SDL_VideoModeOK(x_size_table[j], y_size_table[j], aScreenDepth[i], SDL_SWSURFACE); - if (bitdepth) - { - #ifdef DEBUG - fprintf(stderr, "Bit depth: %d\n", bitdepth); - #endif - gfxvidinfo.width = current_width = x_size_table[j]; - gfxvidinfo.height = current_height = y_size_table[j]; - break; - } - else - { - fprintf(stderr, "Video mode %dx%d@%d not available\n", current_width, current_height, aScreenDepth[i]); - } - } - } - if (bitdepth == 0) - { - fprintf(stderr, "No video mode found!\n"); - return 0; - } + } else { + display = screen; } - graphics_subinit (); + /* Set UAE window title and icon name */ + SDL_WM_SetCaption (PACKAGE_NAME, PACKAGE_NAME); + + /* Mouse is now always grabbed when full-screen - to work around + * problems with full-screen mouse input in some SDL implementations */ + if (fullscreen) + SDL_WM_GrabInput (SDL_GRAB_ON); + else + SDL_WM_GrabInput (mousegrab ? SDL_GRAB_ON : SDL_GRAB_OFF); + + /* Hide mouse cursor */ + SDL_ShowCursor (/*currprefs.hide_cursor || */fullscreen || mousegrab ? SDL_DISABLE : SDL_ENABLE); + + inputdevice_release_all_keys (); + reset_hotkeys (); + +#ifdef PICASSO96 + if (!screen_is_picasso) { +#endif + /* Initialize structure for Amiga video modes */ + if (is_hwsurface) { + SDL_LockSurface (display); + gfxvidinfo.bufmem = 0; + gfxvidinfo.emergmem = malloc (display->pitch); + gfxvidinfo.maxblocklines = 0; + SDL_UnlockSurface (display); + } + + if (!is_hwsurface) { + gfxvidinfo.bufmem = display->pixels; + gfxvidinfo.emergmem = 0; + gfxvidinfo.maxblocklines = gfxvidinfo.height; + } + gfxvidinfo.linemem = 0; + gfxvidinfo.pixbytes = display->format->BytesPerPixel; + bit_unit = display->format->BytesPerPixel * 8; + gfxvidinfo.rowbytes = display->pitch; + + SDL_SetColors (display, arSDLColors, 0, 256); - if (!init_colors ()) - return 0; + reset_drawing (); - buttonstate[0] = buttonstate[1] = buttonstate[2] = 0; - for (i = 0; i < 256; i++) - keystate[i] = 0; + /* Force recalculation of row maps - if we're locking */ + old_pixels = (void *)-1; +#ifdef PICASSO96 + } else { + /* Initialize structure for Picasso96 video modes */ + picasso_vidinfo.rowbytes = display->pitch; + picasso_vidinfo.extra_mem = 1; + picasso_vidinfo.depth = bitdepth; + picasso_has_invalid_lines = 0; + picasso_invalid_start = picasso_vidinfo.height + 1; + picasso_invalid_stop = -1; + + memset (picasso_invalid_lines, 0, sizeof picasso_invalid_lines); + } +#endif + } return 1; } -static void graphics_subshutdown (void) +int graphics_init (void) { -#ifdef DEBUG - fprintf(stderr, "Function: graphics_subshutdown\n"); + int success = 0; + + DEBUG_LOG ("Function: graphics_init\n"); + + if (currprefs.color_mode > 5) { + write_log ("Bad color mode selected. Using default.\n"); + currprefs.color_mode = 0; + } + +#ifdef PICASSO96 + screen_is_picasso = 0; #endif + mousegrab = 0; + + fixup_prefs_dimensions (&currprefs.gfx_w); + fixup_prefs_dimensions (&currprefs.gfx_f); - SDL_FreeSurface(prSDLScreen); + if (graphics_subinit ()) { + if (init_colors ()) { + success = 1; + } + } + return success; } -void graphics_leave (void) +static void graphics_subshutdown (int final) { -#ifdef DEBUG - fprintf(stderr, "Function: graphics_leave\n"); -#endif + DEBUG_LOG ("Function: graphics_subshutdown\n"); - graphics_subshutdown (); + if (display && display != screen) + SDL_FreeSurface (display); - SDL_VideoQuit(); + /* XRandR requires that clients sometimes have to retry a request for + changing screen size, which SDL doesn't do. Work around the problem + by reinitializing SDL. */ + SDL_QuitSubSystem (SDL_INIT_VIDEO); + SDL_InitSubSystem (SDL_INIT_VIDEO); + if (fullscreen) + /* Try switching back to the previous screenmode. */ + SDL_SetVideoMode (screenmode[0].w, screenmode[0].h, bitdepth, SDL_FULLSCREEN); - dumpcustom (); -} + display = screen = 0; -/* Decode KeySyms. This function knows about all keys that are common - * between different keyboard languages. */ -static int kc_decode (SDL_keysym *prKeySym) -{ - switch (prKeySym->sym) - { - case SDLK_b: return AK_B; - case SDLK_c: return AK_C; - case SDLK_d: return AK_D; - case SDLK_e: return AK_E; - case SDLK_f: return AK_F; - case SDLK_g: return AK_G; - case SDLK_h: return AK_H; - case SDLK_i: return AK_I; - case SDLK_j: return AK_J; - case SDLK_k: return AK_K; - case SDLK_l: return AK_L; - case SDLK_n: return AK_N; - case SDLK_o: return AK_O; - case SDLK_p: return AK_P; - case SDLK_r: return AK_R; - case SDLK_s: return AK_S; - case SDLK_t: return AK_T; - case SDLK_u: return AK_U; - case SDLK_v: return AK_V; - case SDLK_x: return AK_X; - - case SDLK_0: return AK_0; - case SDLK_1: return AK_1; - case SDLK_2: return AK_2; - case SDLK_3: return AK_3; - case SDLK_4: return AK_4; - case SDLK_5: return AK_5; - case SDLK_6: return AK_6; - case SDLK_7: return AK_7; - case SDLK_8: return AK_8; - case SDLK_9: return AK_9; - - case SDLK_KP0: return AK_NP0; - case SDLK_KP1: return AK_NP1; - case SDLK_KP2: return AK_NP2; - case SDLK_KP3: return AK_NP3; - case SDLK_KP4: return AK_NP4; - case SDLK_KP5: return AK_NP5; - case SDLK_KP6: return AK_NP6; - case SDLK_KP7: return AK_NP7; - case SDLK_KP8: return AK_NP8; - case SDLK_KP9: return AK_NP9; - case SDLK_KP_DIVIDE: return AK_NPDIV; - case SDLK_KP_MULTIPLY: return AK_NPMUL; - case SDLK_KP_MINUS: return AK_NPSUB; - case SDLK_KP_PLUS: return AK_NPADD; - case SDLK_KP_PERIOD: return AK_NPDEL; - case SDLK_KP_ENTER: return AK_ENT; - - case SDLK_F1: return AK_F1; - case SDLK_F2: return AK_F2; - case SDLK_F3: return AK_F3; - case SDLK_F4: return AK_F4; - case SDLK_F5: return AK_F5; - case SDLK_F6: return AK_F6; - case SDLK_F7: return AK_F7; - case SDLK_F8: return AK_F8; - case SDLK_F9: return AK_F9; - case SDLK_F10: return AK_F10; - - case SDLK_BACKSPACE: return AK_BS; - case SDLK_DELETE: return AK_DEL; - case SDLK_LCTRL: return AK_CTRL; - case SDLK_RCTRL: return AK_RCTRL; - case SDLK_TAB: return AK_TAB; - case SDLK_LALT: return AK_LALT; - case SDLK_RALT: return AK_RALT; - case SDLK_RMETA: return AK_RAMI; - case SDLK_LMETA: return AK_LAMI; - case SDLK_RETURN: return AK_RET; - case SDLK_SPACE: return AK_SPC; - case SDLK_LSHIFT: return AK_LSH; - case SDLK_RSHIFT: return AK_RSH; - case SDLK_ESCAPE: return AK_ESC; - - case SDLK_INSERT: return AK_HELP; - case SDLK_HOME: return AK_NPLPAREN; - case SDLK_END: return AK_NPRPAREN; - case SDLK_CAPSLOCK: return AK_CAPSLOCK; - - case SDLK_UP: return AK_UP; - case SDLK_DOWN: return AK_DN; - case SDLK_LEFT: return AK_LF; - case SDLK_RIGHT: return AK_RT; - - case SDLK_PAGEUP: return AK_RAMI; /* PgUp mapped to right amiga */ - case SDLK_PAGEDOWN: return AK_LAMI; /* PgDn mapped to left amiga */ - - default: return -1; - } -} - -static int decode_fr (SDL_keysym *prKeySym) -{ - switch(prKeySym->sym) - { - /* FR specific */ - case SDLK_a: return AK_Q; - case SDLK_m: return AK_SEMICOLON; - case SDLK_q: return AK_A; - case SDLK_y: return AK_Y; - case SDLK_w: return AK_Z; - case SDLK_z: return AK_W; - case SDLK_LEFTBRACKET: return AK_LBRACKET; - case SDLK_RIGHTBRACKET: return AK_RBRACKET; - case SDLK_COMMA: return AK_M; - case SDLK_LESS: case SDLK_GREATER: return AK_LTGT; - case SDLK_PERIOD: case SDLK_SEMICOLON: return AK_COMMA; - case SDLK_RIGHTPAREN: return AK_MINUS; - case SDLK_EQUALS: return AK_SLASH; - case SDLK_HASH: return AK_NUMBERSIGN; - case SDLK_SLASH: return AK_PERIOD; - case SDLK_MINUS: return AK_EQUAL; - case SDLK_BACKSLASH: return AK_BACKSLASH; - default: return -1; - } -} - -static int decode_us (SDL_keysym *prKeySym) -{ - switch(prKeySym->sym) - { - /* US specific */ - case SDLK_a: return AK_A; - case SDLK_m: return AK_M; - case SDLK_q: return AK_Q; - case SDLK_y: return AK_Y; - case SDLK_w: return AK_W; - case SDLK_z: return AK_Z; - case SDLK_LEFTBRACKET: return AK_LBRACKET; - case SDLK_RIGHTBRACKET: return AK_RBRACKET; - case SDLK_COMMA: return AK_COMMA; - case SDLK_PERIOD: return AK_PERIOD; - case SDLK_SLASH: return AK_SLASH; - case SDLK_SEMICOLON: return AK_SEMICOLON; - case SDLK_MINUS: return AK_MINUS; - case SDLK_EQUALS: return AK_EQUAL; - /* this doesn't work: */ - case SDLK_BACKQUOTE: return AK_QUOTE; - case SDLK_QUOTE: return AK_BACKQUOTE; - case SDLK_BACKSLASH: return AK_BACKSLASH; - default: return -1; - } -} - -static int decode_de (SDL_keysym *prKeySym) -{ - switch(prKeySym->sym) - { - /* DE specific */ - case SDLK_a: return AK_A; - case SDLK_m: return AK_M; - case SDLK_q: return AK_Q; - case SDLK_w: return AK_W; - case SDLK_y: return AK_Z; - case SDLK_z: return AK_Y; - /* German umlaut oe */ - case SDLK_WORLD_86: return AK_SEMICOLON; - /* German umlaut ae */ - case SDLK_WORLD_68: return AK_QUOTE; - /* German umlaut ue */ - case SDLK_WORLD_92: return AK_LBRACKET; - case SDLK_PLUS: case SDLK_ASTERISK: return AK_RBRACKET; - case SDLK_COMMA: return AK_COMMA; - case SDLK_PERIOD: return AK_PERIOD; - case SDLK_LESS: case SDLK_GREATER: return AK_LTGT; - case SDLK_HASH: return AK_NUMBERSIGN; - /* German sharp s */ - case SDLK_WORLD_63: return AK_MINUS; - case SDLK_QUOTE: return AK_EQUAL; - case SDLK_CARET: return AK_BACKQUOTE; - case SDLK_MINUS: return AK_SLASH; - default: return -1; - } -} - -static int decode_se (SDL_keysym *prKeySym) -{ - switch(prKeySym->sym) - { - /* SE specific */ - case SDLK_a: return AK_A; - case SDLK_m: return AK_M; - case SDLK_q: return AK_Q; - case SDLK_w: return AK_W; - case SDLK_y: return AK_Y; - case SDLK_z: return AK_Z; - case SDLK_WORLD_86: return AK_SEMICOLON; - case SDLK_WORLD_68: return AK_QUOTE; - case SDLK_WORLD_69: return AK_LBRACKET; - case SDLK_COMMA: return AK_COMMA; - case SDLK_PERIOD: return AK_PERIOD; - case SDLK_MINUS: return AK_SLASH; - case SDLK_LESS: case SDLK_GREATER: return AK_LTGT; - case SDLK_PLUS: case SDLK_QUESTION: return AK_EQUAL; - case SDLK_AT: case SDLK_WORLD_29: return AK_BACKQUOTE; - case SDLK_CARET: return AK_RBRACKET; - case SDLK_BACKSLASH: return AK_MINUS; - case SDLK_HASH: return AK_NUMBERSIGN; - default: return -1; - } -} - -static int decode_it (SDL_keysym *prKeySym) -{ - switch(prKeySym->sym) - { - /* IT specific */ - case SDLK_a: return AK_A; - case SDLK_m: return AK_M; - case SDLK_q: return AK_Q; - case SDLK_w: return AK_W; - case SDLK_y: return AK_Y; - case SDLK_z: return AK_Z; - case SDLK_WORLD_82: return AK_SEMICOLON; - case SDLK_WORLD_64: return AK_QUOTE; - case SDLK_WORLD_72: return AK_LBRACKET; - case SDLK_PLUS: case SDLK_ASTERISK: return AK_RBRACKET; - case SDLK_COMMA: return AK_COMMA; - case SDLK_PERIOD: return AK_PERIOD; - case SDLK_LESS: case SDLK_GREATER: return AK_LTGT; - case SDLK_BACKSLASH: return AK_BACKQUOTE; - case SDLK_QUOTE: return AK_MINUS; - case SDLK_WORLD_76: return AK_EQUAL; - case SDLK_MINUS: return AK_SLASH; - case SDLK_HASH: return AK_NUMBERSIGN; - default: return -1; - } -} - -static int decode_es (SDL_keysym *prKeySym) -{ - switch(prKeySym->sym) - { - /* ES specific */ - case SDLK_a: return AK_A; - case SDLK_m: return AK_M; - case SDLK_q: return AK_Q; - case SDLK_w: return AK_W; - case SDLK_y: return AK_Y; - case SDLK_z: return AK_Z; - case SDLK_WORLD_81: return AK_SEMICOLON; - case SDLK_PLUS: case SDLK_ASTERISK: return AK_RBRACKET; - case SDLK_COMMA: return AK_COMMA; - case SDLK_PERIOD: return AK_PERIOD; - case SDLK_LESS: case SDLK_GREATER: return AK_LTGT; - case SDLK_BACKSLASH: return AK_BACKQUOTE; - case SDLK_QUOTE: return AK_MINUS; - case SDLK_WORLD_76: return AK_EQUAL; - case SDLK_MINUS: return AK_SLASH; - case SDLK_HASH: return AK_NUMBERSIGN; - default: return -1; - } -} - -static int keycode2amiga(SDL_keysym *prKeySym) -{ - int iAmigaKeycode = kc_decode(prKeySym); - if (iAmigaKeycode == -1) - { - switch (currprefs.keyboard_lang) - { - case KBD_LANG_FR: - return decode_fr(prKeySym); - case KBD_LANG_US: - return decode_us(prKeySym); - case KBD_LANG_DE: - return decode_de(prKeySym); - case KBD_LANG_SE: - return decode_se (prKeySym); - case KBD_LANG_IT: - return decode_it (prKeySym); - case KBD_LANG_ES: - return decode_es (prKeySym); - default: - return -1; - } + if (gfxvidinfo.emergmem) { + free (gfxvidinfo.emergmem); + gfxvidinfo.emergmem = 0; } - return iAmigaKeycode; +} + +void graphics_leave (void) +{ + DEBUG_LOG ("Function: graphics_leave\n"); + + graphics_subshutdown (1); + SDL_QuitSubSystem (SDL_INIT_VIDEO); + dumpcustom (); } static int refresh_necessary = 0; @@ -729,139 +653,97 @@ static int refresh_necessary = 0; void handle_events (void) { SDL_Event rEvent; - int iAmigaKeyCode; - int i, j; - int iIsHotKey = 0; -#ifdef DEBUG - fprintf(stderr, "Function: handle_events\n"); -#endif - /* Handle GUI events */ gui_handle_events (); - while (SDL_PollEvent(&rEvent)) - { - switch (rEvent.type) - { - case SDL_QUIT: -#ifdef DEBUG - fprintf(stderr, "Event: quit\n"); -#endif - uae_quit(); - break; - case SDL_KEYDOWN: -#ifdef DEBUG - fprintf(stderr, "Event: key down\n"); + while (SDL_PollEvent (&rEvent)) { + switch (rEvent.type) { + case SDL_QUIT: + DEBUG_LOG ("Event: quit\n"); + uae_quit(); + break; + + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: { + int state = (rEvent.type == SDL_MOUSEBUTTONDOWN); + int buttonno = -1; + + DEBUG_LOG ("Event: mouse button %d %s\n", rEvent.button.button, state ? "down" : "up"); + + switch (rEvent.button.button) { + case SDL_BUTTON_LEFT: buttonno = 0; break; + case SDL_BUTTON_MIDDLE: buttonno = 2; break; + case SDL_BUTTON_RIGHT: buttonno = 1; break; +#ifdef SDL_BUTTON_WHEELUP + case SDL_BUTTON_WHEELUP: if (state) record_key (0x7a << 1); break; + case SDL_BUTTON_WHEELDOWN: if (state) record_key (0x7b << 1); break; #endif - /* Check for hotkey sequence */ - i = 0; - while (arHotKeys[i].pfHandler != NULL) - { - if (rEvent.key.keysym.sym == arHotKeys[i].aHotKeys[0]) - { - arHotKeys[i].aPressedKeys[0] = 1; - iIsHotKey = 1; } - if (arHotKeys[i].aPressedKeys[0] == 1 && - rEvent.key.keysym.sym == arHotKeys[i].aHotKeys[1]) - { - arHotKeys[i].aPressedKeys[1] = 1; - arHotKeys[i].pfHandler(); - iIsHotKey = 1; - } - i++; + if (buttonno >= 0) + setmousebuttonstate (0, buttonno, rEvent.type == SDL_MOUSEBUTTONDOWN ? 1:0); + break; } - if (iIsHotKey == 0) - { - /* No hotkey sequence */ - iAmigaKeyCode = keycode2amiga(&(rEvent.key.keysym)); - if (iAmigaKeyCode >= 0) - { - if (!keystate[iAmigaKeyCode]) - { - keystate[iAmigaKeyCode] = 1; - record_key(iAmigaKeyCode << 1); - } + + case SDL_KEYUP: + case SDL_KEYDOWN: { + int state = (rEvent.type == SDL_KEYDOWN); + int keycode; + int ievent; + + keycode = rEvent.key.keysym.sym; + + DEBUG_LOG ("Event: key %d %s\n", keycode, state ? "down" : "up"); + + if ((ievent = match_hotkey_sequence (keycode, state))) { + DEBUG_LOG ("Hotkey event: %d\n", ievent); + handle_hotkey_event (ievent, state); + } else { + inputdevice_do_keyboard (keysym2amiga (keycode), state); } + break; } - break; - case SDL_KEYUP: -#ifdef DEBUG - fprintf(stderr, "Event: key up\n"); -#endif - /* Check for hotkey sequence */ - i = 0; - while (arHotKeys[i].pfHandler != NULL) - { - for (j = 0; j < 2; j++) - { - if (rEvent.key.keysym.sym == arHotKeys[i].aHotKeys[j] && - arHotKeys[i].aPressedKeys[j] == 1) - { - arHotKeys[i].aPressedKeys[j] = 0; - iIsHotKey = 1; - } + + case SDL_MOUSEMOTION: + //DEBUG_LOG ("Event: mouse motion\n"); + + if (!fullscreen && !mousegrab) { + setmousestate (0, 0,rEvent.motion.x, 1); + setmousestate (0, 1,rEvent.motion.y, 1); + } else { + setmousestate (0, 0, rEvent.motion.xrel, 0); + setmousestate (0, 1, rEvent.motion.yrel, 0); } - i++; - } - if (iIsHotKey == 0) - { - iAmigaKeyCode = keycode2amiga(&(rEvent.key.keysym)); - if (iAmigaKeyCode >= 0) - { - keystate[iAmigaKeyCode] = 0; - record_key((iAmigaKeyCode << 1) | 1); + break; + + case SDL_ACTIVEEVENT: + if (rEvent.active.state & SDL_APPINPUTFOCUS && !rEvent.active.gain) { + DEBUG_LOG ("Lost input focus\n"); + inputdevice_release_all_keys (); + reset_hotkeys (); } - } - break; - case SDL_MOUSEBUTTONDOWN: -#ifdef DEBUG - fprintf(stderr, "Event: mouse button down\n"); -#endif - buttonstate[rEvent.button.button-1] = 1; - break; - case SDL_MOUSEBUTTONUP: -#ifdef DEBUG - fprintf(stderr, "Event: mouse button up\n"); -#endif - buttonstate[rEvent.button.button-1] = 0; - break; - case SDL_MOUSEMOTION: -#ifdef DEBUG - fprintf(stderr, "Event: mouse motion\n"); -#endif - newmousecounters = 1; - lastmx += rEvent.motion.xrel; - lastmy += rEvent.motion.yrel; - break; - } - } -#if defined PICASSO96 - if (screen_is_picasso && refresh_necessary) - { - SDL_UpdateRect(prSDLScreen, 0, 0, picasso_vidinfo.width, picasso_vidinfo.height); + break; + } /* end switch() */ + } /* end while() */ + +#ifdef PICASSO96 + if (screen_is_picasso && refresh_necessary) { + SDL_UpdateRect (screen, 0, 0, picasso_vidinfo.width, picasso_vidinfo.height); refresh_necessary = 0; memset (picasso_invalid_lines, 0, sizeof picasso_invalid_lines); - } - else if (screen_is_picasso && picasso_has_invalid_lines) - { + } else if (screen_is_picasso && picasso_has_invalid_lines) { int i; int strt = -1; picasso_invalid_lines[picasso_vidinfo.height] = 0; - for (i = picasso_invalid_start; i < picasso_invalid_stop + 2; i++) - { - if (picasso_invalid_lines[i]) - { + for (i = picasso_invalid_start; i < picasso_invalid_stop + 2; i++) { + if (picasso_invalid_lines[i]) { picasso_invalid_lines[i] = 0; if (strt != -1) continue; strt = i; - } - else - { + } else { if (strt == -1) continue; - SDL_UpdateRect(prSDLScreen, 0, strt, picasso_vidinfo.width, i-strt); + SDL_UpdateRect (screen, 0, strt, picasso_vidinfo.width, i - strt); strt = -1; } } @@ -872,59 +754,57 @@ void handle_events (void) picasso_invalid_start = picasso_vidinfo.height + 1; picasso_invalid_stop = -1; #endif +} - /* Handle UAE reset */ - if ((keystate[AK_CTRL] || keystate[AK_RCTRL]) && keystate[AK_LAMI] && keystate[AK_RAMI]) - uae_reset (); +static void switch_keymaps (void) +{ + set_default_hotkeys (get_default_cooked_hotkeys ()); } int check_prefs_changed_gfx (void) { + int a_changed = 0, p_changed = 0; - if (changed_prefs.gfx_width != currprefs.gfx_width - || changed_prefs.gfx_height != currprefs.gfx_height) - { - fixup_prefs_dimensions (&changed_prefs); - } - - if (changed_prefs.gfx_width == currprefs.gfx_width - && changed_prefs.gfx_height == currprefs.gfx_height - && changed_prefs.gfx_lores == currprefs.gfx_lores - && changed_prefs.gfx_linedbl == currprefs.gfx_linedbl - && changed_prefs.gfx_correct_aspect == currprefs.gfx_correct_aspect - && changed_prefs.gfx_xcenter == currprefs.gfx_xcenter - && changed_prefs.gfx_ycenter == currprefs.gfx_ycenter - && changed_prefs.gfx_afullscreen == currprefs.gfx_afullscreen - && changed_prefs.gfx_pfullscreen == currprefs.gfx_pfullscreen) - { - return 0; + if (!screen_is_picasso) { + if (!fullscreen + && memcmp (&changed_prefs.gfx_w, &currprefs.gfx_w, sizeof (struct gfx_params)) != 0) + { + a_changed = 1; + fixup_prefs_dimensions (&changed_prefs.gfx_w); + currprefs.gfx_w = changed_prefs.gfx_w; + } else if (fullscreen + && memcmp (&changed_prefs.gfx_f, &currprefs.gfx_f, sizeof (struct gfx_params)) != 0) + { + a_changed = 1; + fixup_prefs_dimensions (&changed_prefs.gfx_f); + currprefs.gfx_f = changed_prefs.gfx_f; + } + if (changed_prefs.gfx_afullscreen != currprefs.gfx_afullscreen) { + a_changed = 1; + } + } else if (changed_prefs.gfx_pfullscreen != currprefs.gfx_pfullscreen) { + p_changed = 1; } -#ifdef DEBUG - fprintf(stderr, "Function: check_prefs_changed_gfx\n"); -#endif - graphics_subshutdown (); - currprefs.gfx_width = changed_prefs.gfx_width; - currprefs.gfx_height = changed_prefs.gfx_height; - currprefs.gfx_lores = changed_prefs.gfx_lores; - currprefs.gfx_linedbl = changed_prefs.gfx_linedbl; - currprefs.gfx_correct_aspect = changed_prefs.gfx_correct_aspect; - currprefs.gfx_xcenter = changed_prefs.gfx_xcenter; - currprefs.gfx_ycenter = changed_prefs.gfx_ycenter; + currprefs.gfx_afullscreen = changed_prefs.gfx_afullscreen; currprefs.gfx_pfullscreen = changed_prefs.gfx_pfullscreen; + if (!a_changed && !p_changed) + return 0; + + DEBUG_LOG ("Function: check_prefs_changed_gfx\n"); + + graphics_subshutdown (0); + gui_update_gfx (); graphics_subinit (); - /* if (! inwindow) - XWarpPointer (display, None, mywin, 0, 0, 0, 0, - current_width / 2, current_height / 2); - */ notice_screen_contents_lost (); init_row_map (); if (screen_is_picasso) picasso_enablescreen (1); + return 0; } @@ -938,28 +818,23 @@ int needmousehack (void) return 1; } -void LED (int on) +int mousehack_allowed (void) { -#if 0 /* Maybe that is responsible for the joystick emulation problems on SunOS? */ - static int last_on = -1; - XKeyboardControl control; + return 1; +} - if (last_on == on) - return; - last_on = on; - control.led = 1; /* implementation defined */ - control.led_mode = on ? LedModeOn : LedModeOff; - XChangeKeyboardControl(display, KBLed | KBLedMode, &control); -#endif +void LED (int on) +{ } #ifdef PICASSO96 void DX_Invalidate (int first, int last) { -#ifdef DEBUG - fprintf(stderr, "Function: DX_Invalidate %i - %i\n", first, last); -#endif + DEBUG_LOG ("Function: DX_Invalidate %i - %i\n", first, last); + + if (is_hwsurface) + return; if (first > last) return; @@ -970,8 +845,7 @@ void DX_Invalidate (int first, int last) if (last > picasso_invalid_stop) picasso_invalid_stop = last; - while (first <= last) - { + while (first <= last) { picasso_invalid_lines[first] = 1; first++; } @@ -982,136 +856,168 @@ int DX_BitsPerCannon (void) return 8; } -static int palette_update_start=256; -static int palette_update_end=0; +static int palette_update_start = 256; +static int palette_update_end = 0; void DX_SetPalette (int start, int count) { -#ifdef DEBUG - fprintf(stderr, "Function: DX_SetPalette_real\n"); -#endif + DEBUG_LOG ("Function: DX_SetPalette_real\n"); if (! screen_is_picasso || picasso96_state.RGBFormat != RGBFB_CHUNKY) return; - if (picasso_vidinfo.pixbytes != 1) - { - /* This is the case when we're emulating a 256 color display. */ - while (count-- > 0) - { + if (picasso_vidinfo.pixbytes != 1) { + /* This is the case when we're emulating a 256 color display. */ + while (count-- > 0) { int r = picasso96_state.CLUT[start].Red; int g = picasso96_state.CLUT[start].Green; int b = picasso96_state.CLUT[start].Blue; - picasso_vidinfo.clut[start++] = (doMask256 (r, red_bits, red_shift) - | doMask256 (g, green_bits, green_shift) - | doMask256 (b, blue_bits, blue_shift)); + picasso_vidinfo.clut[start++] = + (doMask256 (r, red_bits, red_shift) + | doMask256 (g, green_bits, green_shift) + | doMask256 (b, blue_bits, blue_shift)); } - return; + } else { + int i; + for (i = start; i < start+count && i < 256; i++) { + p96Colors[i].r = picasso96_state.CLUT[i].Red; + p96Colors[i].g = picasso96_state.CLUT[i].Green; + p96Colors[i].b = picasso96_state.CLUT[i].Blue; + } + SDL_SetColors (screen, &p96Colors[start], start, count); } +} - while (count-- > 0) - { #if 0 - XColor col = parsed_xcolors[start]; - col.red = picasso96_state.CLUT[start].Red * 0x0101; - col.green = picasso96_state.CLUT[start].Green * 0x0101; - col.blue = picasso96_state.CLUT[start].Blue * 0x0101; - XStoreColor (display, cmap, &col); -#endif - start++; +void DX_SetPalette_vsync(void) +{ + if (palette_update_end > palette_update_start) { + DX_SetPalette (palette_update_start, + palette_update_end - palette_update_start); + palette_update_end = 0; + palette_update_start = 0; + } +} + +int DX_Fill (int dstx, int dsty, int width, int height, uae_u32 color, RGBFTYPE rgbtype) +{ + int result = 0; + SDL_Rect rect = {dstx, dsty, width, height}; + + DEBUG_LOG ("DX_Fill (x:%d y:%d w:%d h:%d color=%08x)\n", dstx, dsty, width, height, color); + + if (SDL_FillRect (screen, &rect, color) == 0) { + DX_Invalidate (dsty, dsty + height - 1); + result = 1; } + return result; } -int DX_FillResolutions (uae_u16 *ppixel_format) +int DX_Blit (int srcx, int srcy, int dstx, int dsty, int width, int height, BLIT_OPCODE opcode) { - int i, count = 0; - int w = 0; - int h = 0; - int emulate_chunky = 0; + int result = 0; + SDL_Rect src_rect = {srcx, srcy, width, height}; + SDL_Rect dest_rect = {dstx, dsty, 0, 0}; -#ifdef DEBUG - fprintf(stderr, "Function: DX_FillResolutions\n"); + DEBUG_LOG ("DX_Blit (sx:%d sy:%d dx:%d dy:%d w:%d h:%d op:%d)\n", + srcx, srcy, dstx, dsty, width, height, opcode); + + if (opcode == BLIT_SRC && SDL_BlitSurface (screen, &src_rect, screen, &dest_rect) == 0) { + DX_Invalidate (dsty, dsty + height - 1); + result = 1; + } + return result; +} #endif - /* Find out, which is the highest resolution the SDL can offer */ - for (i = MAX_SCREEN_MODES-1; i>=0; i--) - { - if (bitdepth == SDL_VideoModeOK(x_size_table[i], y_size_table[i], bitdepth, SDL_SWSURFACE)) - { - w = x_size_table[i]; - h = y_size_table[i]; - break; +/* + * Add a screenmode to the emulated P96 display database + */ +static void add_p96_mode (int width, int height, int emulate_chunky, int *count) +{ + unsigned int i; + + for (i = 0; i <= (emulate_chunky ? 1 : 0); i++) { + if (*count < MAX_PICASSO_MODES) { + DisplayModes[*count].res.width = width; + DisplayModes[*count].res.height = height; + DisplayModes[*count].depth = (i == 1) ? 1 : bit_unit >> 3; + DisplayModes[*count].refresh = 75; + (*count)++; + + write_log ("SDLGFX: Added P96 mode: %dx%dx%d\n", width, height, (i == 1) ? 8 : bitdepth); } } + return; +} -#ifdef DEBUG - fprintf(stderr, "Max. Picasso screen size: %d x %d\n", w, h); -#endif +int DX_FillResolutions (uae_u16 *ppixel_format) +{ + int i; + int count = 0; + int emulate_chunky = 0; + + DEBUG_LOG ("Function: DX_FillResolutions\n"); - picasso_vidinfo.rgbformat = (bit_unit == 8 ? RGBFB_CHUNKY - : bitdepth == 15 && bit_unit == 16 ? RGBFB_R5G5B5PC - : bitdepth == 16 && bit_unit == 16 ? RGBFB_R5G6B5PC - : bit_unit == 24 ? RGBFB_B8G8R8 - : bit_unit == 32 ? RGBFB_B8G8R8A8 - : RGBFB_NONE); + /* Find supported pixel formats */ + picasso_vidinfo.rgbformat = get_p96_pixel_format (SDL_GetVideoInfo()->vfmt); *ppixel_format = 1 << picasso_vidinfo.rgbformat; - if (bit_unit == 16 || bit_unit == 32) - { + if (bit_unit == 16 || bit_unit == 32) { *ppixel_format |= RGBFF_CHUNKY; emulate_chunky = 1; } - for (i = 0; i < MAX_SCREEN_MODES && count < MAX_PICASSO_MODES; i++) - { + /* Check list of standard P96 screenmodes */ + for (i = 0; i < MAX_SCREEN_MODES; i++) { + if (SDL_VideoModeOK (x_size_table[i], y_size_table[i], bitdepth, + SDL_HWSURFACE | SDL_FULLSCREEN)) { + add_p96_mode (x_size_table[i], y_size_table[i], emulate_chunky, &count); + } + } + + /* Check list of supported SDL screenmodes */ + for (i = 0; i < mode_count; i++) { int j; - for (j = 0; j <= emulate_chunky && count < MAX_PICASSO_MODES; j++) - { - if (x_size_table[i] <= w && y_size_table[i] <= h) + int found = 0; + for (j = 0; j < MAX_SCREEN_MODES - 1; j++) { + if (screenmode[i].w == x_size_table[j] && + screenmode[i].h == y_size_table[j]) { - if (x_size_table[i] > picasso_maxw) - picasso_maxw = x_size_table[i]; - if (y_size_table[i] > picasso_maxh) - picasso_maxh = y_size_table[i]; - DisplayModes[count].res.width = x_size_table[i]; - DisplayModes[count].res.height = y_size_table[i]; - DisplayModes[count].depth = j == 1 ? 1 : bit_unit >> 3; - DisplayModes[count].refresh = 75; -#ifdef DEBUG - fprintf(stderr, "Picasso resolution %d x %d @ %d allowed\n", DisplayModes[count].res.width, DisplayModes[count].res.height, DisplayModes[count].depth); -#endif - - count++; + found = 1; + break; } } + + /* If SDL mode is not a standard P96 mode (and thus already added to the + * list, above) then add it */ + if (!found) + add_p96_mode (screenmode[i].w, screenmode[i].h, emulate_chunky, &count); } -#ifdef DEBUG - fprintf(stderr, "Max. Picasso screen size: %d x %d\n", picasso_maxw, picasso_maxh); -#endif + return count; } static void set_window_for_picasso (void) { -#ifdef DEBUG - fprintf(stderr, "Function: set_window_for_picasso\n"); -#endif - + DEBUG_LOG ("Function: set_window_for_picasso\n"); +#if 0 if (current_width == picasso_vidinfo.width && current_height == picasso_vidinfo.height) - return; + return; +#endif - current_width = picasso_vidinfo.width; - current_height = picasso_vidinfo.height; - graphics_subshutdown (); - graphics_subinit (); -// XResizeWindow (display, mywin, current_width, current_height); + graphics_subshutdown(0); + graphics_subinit(); } void gfx_set_picasso_modeinfo (int w, int h, int depth, int rgbfmt) { -#ifdef DEBUG - fprintf(stderr, "Function: gfx_set_picasso_modeinfo w: %i h: %i depth: %i rgbfmt: %i\n",w, h, depth, rgbfmt); -#endif + DEBUG_LOG ("Function: gfx_set_picasso_modeinfo w: %i h: %i depth: %i rgbfmt: %i\n", w, h, depth, rgbfmt); + + if (screen_is_picasso + && picasso_vidinfo.width == w + && picasso_vidinfo.height == h) + return; picasso_vidinfo.width = w; picasso_vidinfo.height = h; @@ -1127,116 +1033,276 @@ void gfx_set_picasso_baseaddr (uaecptr a void gfx_set_picasso_state (int on) { -#ifdef DEBUG - fprintf(stderr, "Function: gfx_set_picasso_state\n"); -#endif + DEBUG_LOG ("Function: gfx_set_picasso_state: %d\n", on); if (on == screen_is_picasso) return; - graphics_subshutdown (); + + graphics_subshutdown (0); screen_is_picasso = on; - if (on) - { - // Set height, width for Picasso gfx - current_width = picasso_vidinfo.width; - current_height = picasso_vidinfo.height; - } - else - { - // Set height, width for Amiga gfx - current_width = gfxvidinfo.width; - current_height = gfxvidinfo.height; - } + graphics_subinit (); + if (on) DX_SetPalette (0, 256); } uae_u8 *gfx_lock_picasso (void) { -#ifdef DEBUG - fprintf(stderr, "Function: gfx_lock_picasso\n"); -#endif - SDL_LockSurface(prSDLScreen); - return prSDLScreen->pixels; + DEBUG_LOG ("Function: gfx_lock_picasso\n"); + + if (SDL_MUSTLOCK (screen)) + SDL_LockSurface (screen); + picasso_vidinfo.rowbytes = screen->pitch; + return screen->pixels; } void gfx_unlock_picasso (void) { -#ifdef DEBUG - fprintf(stderr, "Function: gfx_unlock_picasso\n"); -#endif - SDL_UnlockSurface(prSDLScreen); + DEBUG_LOG ("Function: gfx_unlock_picasso\n"); + + if (SDL_MUSTLOCK (screen)) + SDL_UnlockSurface (screen); } -#endif +#endif /* PICASSO96 */ -int lockscr (void) +void toggle_fullscreen (void) +{ + changed_prefs.gfx_afullscreen = changed_prefs.gfx_pfullscreen = !fullscreen; + + DEBUG_LOG ("ToggleFullScreen: %d\n", fullscreen ); +}; + +void toggle_mousegrab (void) +{ + if (!fullscreen) { + if (SDL_WM_GrabInput (SDL_GRAB_QUERY) == SDL_GRAB_OFF) { + if (SDL_WM_GrabInput (SDL_GRAB_ON) == SDL_GRAB_ON) { + SDL_WarpMouse (0, 0); + mousegrab = 1; + SDL_ShowCursor (SDL_DISABLE); + } + } else { + if (SDL_WM_GrabInput (SDL_GRAB_OFF) == SDL_GRAB_OFF) { + mousegrab = 0; + SDL_ShowCursor (SDL_DISABLE); + } + } + } +} + +void screenshot (int mode) +{ + write_log ("Screenshot not supported yet\n"); +} + +/* + * Mouse inputdevice functions + */ + +/* Hardwire for 3 axes and 3 buttons - although SDL doesn't + * currently support a Z-axis as such. Mousewheel events are supplied + * as buttons 4 and 5 + */ +#define MAX_BUTTONS 3 +#define MAX_AXES 3 +#define FIRST_AXIS 0 +#define FIRST_BUTTON MAX_AXES + +static int init_mouse (void) +{ + return 1; +} + +static void close_mouse (void) +{ + return; +} + +static int acquire_mouse (unsigned int num, int flags) +{ + /* SDL supports only one mouse */ + return 1; +} + +static void unacquire_mouse (unsigned int num) +{ + return; +} + +static unsigned int get_mouse_num (void) { -#ifdef DEBUG - fprintf(stderr, "Function: lockscr\n"); -#endif - SDL_LockSurface(prSDLScreen); return 1; } -void unlockscr (void) +static const char *get_mouse_name (unsigned int mouse) { -#ifdef DEBUG - fprintf(stderr, "Function: unlockscr\n"); -#endif - SDL_UnlockSurface(prSDLScreen); + return "Default mouse"; } -static void handle_mousegrab (void) +static unsigned int get_mouse_widget_num (unsigned int mouse) { - if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) - { - SDL_WM_GrabInput(SDL_GRAB_ON); - SDL_WarpMouse(0, 0); + return MAX_AXES + MAX_BUTTONS; +} + +static int get_mouse_widget_first (unsigned int mouse, int type) +{ + switch (type) { + case IDEV_WIDGET_BUTTON: + return FIRST_BUTTON; + case IDEV_WIDGET_AXIS: + return FIRST_AXIS; } - else - { - SDL_WM_GrabInput(SDL_GRAB_OFF); + return -1; +} + +static int get_mouse_widget_type (unsigned int mouse, unsigned int num, char *name, uae_u32 *code) +{ + if (num >= MAX_AXES && num < MAX_AXES + MAX_BUTTONS) { + if (name) + sprintf (name, "Button %d", num + 1 + MAX_AXES); + return IDEV_WIDGET_BUTTON; + } else if (num < MAX_AXES) { + if (name) + sprintf (name, "Axis %d", num + 1); + return IDEV_WIDGET_AXIS; } + return IDEV_WIDGET_NONE; } -static void handle_inhibit (void) +static void read_mouse (void) { - toggle_inhibit_frame (IHF_SCROLLLOCK); + /* We handle mouse input in handle_events() */ } +struct inputdevice_functions inputdevicefunc_mouse = { + init_mouse, + close_mouse, + acquire_mouse, + unacquire_mouse, + read_mouse, + get_mouse_num, + get_mouse_name, + get_mouse_widget_num, + get_mouse_widget_type, + get_mouse_widget_first +}; + +/* + * Keyboard inputdevice functions + */ +static unsigned int get_kb_num (void) +{ + /* SDL supports only one keyboard */ + return 1; +} -static void handle_interpol (void) +static const char *get_kb_name (unsigned int kb) { - if (currprefs.sound_interpol == 0) - { - currprefs.sound_interpol = 1; - printf ("Interpol on: rh\n"); - } - else if (currprefs.sound_interpol == 1) - { - currprefs.sound_interpol = 2; - printf ("Interpol on: crux\n"); - } - else - { - currprefs.sound_interpol = 0; - printf ("Interpol off\n"); + return "Default keyboard"; +} + +static unsigned int get_kb_widget_num (unsigned int kb) +{ + return 255; // fix me +} + +static int get_kb_widget_first (unsigned int kb, int type) +{ + return 0; +} + +static int get_kb_widget_type (unsigned int kb, unsigned int num, char *name, uae_u32 *code) +{ + // fix me + *code = num; + return IDEV_WIDGET_KEY; +} + +static int init_kb (void) +{ + struct uae_input_device_kbr_default *keymap = 0; + + /* See if we support raw keys on this platform */ + if ((keymap = get_default_raw_keymap (get_sdlgfx_type ())) != 0) { + inputdevice_setkeytranslation (keymap); + have_rawkeys = 1; } + switch_keymaps (); + + return 1; +} + +static void close_kb (void) +{ +} + +static int keyhack (int scancode, int pressed, int num) +{ + return scancode; } -static void framerate_up (void) +static void read_kb (void) { - if (currprefs.gfx_framerate < 20) - changed_prefs.gfx_framerate = currprefs.gfx_framerate + 1; } -static void framerate_down (void) +static int acquire_kb (unsigned int num, int flags) { - if (currprefs.gfx_framerate > 1) - changed_prefs.gfx_framerate = currprefs.gfx_framerate - 1; + return 1; } +static void unacquire_kb (unsigned int num) +{ +} + +struct inputdevice_functions inputdevicefunc_keyboard = +{ + init_kb, + close_kb, + acquire_kb, + unacquire_kb, + read_kb, + get_kb_num, + get_kb_name, + get_kb_widget_num, + get_kb_widget_type, + get_kb_widget_first +}; + +//static int capslockstate; + +int getcapslockstate (void) +{ +// TODO +// return capslockstate; + return 0; +} +void setcapslockstate (int state) +{ +// TODO +// capslockstate = state; +} + + +/* + * Default inputdevice config for SDL mouse + */ +void input_get_default_mouse (struct uae_input_device *uid) +{ + /* SDL supports only one mouse */ + uid[0].eventid[ID_AXIS_OFFSET + 0][0] = INPUTEVENT_MOUSE1_HORIZ; + uid[0].eventid[ID_AXIS_OFFSET + 1][0] = INPUTEVENT_MOUSE1_VERT; + uid[0].eventid[ID_AXIS_OFFSET + 2][0] = INPUTEVENT_MOUSE1_WHEEL; + uid[0].eventid[ID_BUTTON_OFFSET + 0][0] = INPUTEVENT_JOY1_FIRE_BUTTON; + uid[0].eventid[ID_BUTTON_OFFSET + 1][0] = INPUTEVENT_JOY1_2ND_BUTTON; + uid[0].eventid[ID_BUTTON_OFFSET + 2][0] = INPUTEVENT_JOY1_3RD_BUTTON; + uid[0].enabled = 1; +} + +/* + * Handle gfx specific cfgfile options + */ + void target_save_options (FILE *f, struct uae_prefs *p) { }