--- BasiliskII/src/SDL/video_sdl.cpp 2004/06/24 21:46:55 1.5 +++ BasiliskII/src/SDL/video_sdl.cpp 2005/03/17 00:19:39 1.16 @@ -1,7 +1,7 @@ /* * video_sdl.cpp - Video/graphics emulation, SDL specific stuff * - * Basilisk II (C) 1997-2004 Christian Bauer + * Basilisk II (C) 1997-2005 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,6 +35,8 @@ * - Events processing is bound to the general emulation thread as SDL requires * to PumpEvents() within the same thread as the one that called SetVideoMode(). * Besides, there can't seem to be a way to call SetVideoMode() from a child thread. + * - Refresh performance is still slow. Use SDL_CreateRGBSurface()? + * - Backport hw cursor acceleration to Basilisk II? */ #include "sysdeps.h" @@ -54,6 +56,7 @@ #include "video.h" #include "video_defs.h" #include "video_blit.h" +#include "vm_alloc.h" #define DEBUG 0 #include "debug.h" @@ -79,7 +82,11 @@ static int display_type = DISPLAY_WINDOW #endif // Constants +#ifdef WIN32 +const char KEYCODE_FILE_NAME[] = "BasiliskII_keycodes"; +#else const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes"; +#endif // Global variables @@ -94,9 +101,11 @@ static uint32 the_buffer_size; // S static bool redraw_thread_active = false; // Flag: Redraw thread installed static volatile bool redraw_thread_cancel; // Flag: Cancel Redraw thread static SDL_Thread *redraw_thread = NULL; // Redraw thread +static volatile bool thread_stop_req = false; +static volatile bool thread_stop_ack = false; // Acknowledge for thread_stop_req #ifdef ENABLE_VOSF -static bool use_vosf = true; // Flag: VOSF enabled +static bool use_vosf = false; // Flag: VOSF enabled #else static const bool use_vosf = false; // VOSF not possible #endif @@ -114,6 +123,8 @@ static int keycode_table[256]; // X // SDL variables static int screen_depth; // Depth of current screen +static SDL_Cursor *sdl_cursor; // Copy of Mac cursor +static volatile bool cursor_changed = false; // Flag: cursor changed, redraw_func must update the cursor static SDL_Color sdl_palette[256]; // Color palette to be used as CLUT and gamma table static bool sdl_palette_changed = false; // Flag: Palette changed, redraw thread must set new colors static const int sdl_eventmask = SDL_MOUSEBUTTONDOWNMASK | SDL_MOUSEBUTTONUPMASK | SDL_MOUSEMOTIONMASK | SDL_KEYUPMASK | SDL_KEYDOWNMASK | SDL_VIDEOEXPOSEMASK | SDL_QUITMASK; @@ -141,6 +152,30 @@ extern void SysMountFirstFloppy(void); /* + * Framebuffer allocation routines + */ + +static void *vm_acquire_framebuffer(uint32 size) +{ +#ifdef SHEEPSHAVER +#ifdef DIRECT_ADDRESSING_HACK + const uint32 FRAME_BUFFER_BASE = 0x61000000; + uint8 *fb = Mac2HostAddr(FRAME_BUFFER_BASE); + if (vm_acquire_fixed(fb, size) < 0) + fb = VM_MAP_FAILED; + return fb; +#endif +#endif + return vm_acquire(size); +} + +static inline void vm_release_framebuffer(void *fb, uint32 size) +{ + vm_release(fb, size); +} + + +/* * SheepShaver glue */ @@ -255,6 +290,12 @@ static void ErrorAlert(int error) { ErrorAlert(GetString(error)); } + +// Display warning alert +static void WarningAlert(int warning) +{ + WarningAlert(GetString(warning)); +} #endif @@ -314,7 +355,7 @@ static inline int bytes_per_pixel(int de } // Map video_mode depth ID to numerical depth value -static int sdl_depth_of_video_depth(int video_depth) +static int mac_depth_of_video_depth(int video_depth) { int depth = -1; switch (video_depth) { @@ -342,6 +383,12 @@ static int sdl_depth_of_video_depth(int return depth; } +// Map video_mode depth ID to SDL screen depth +static int sdl_depth_of_video_depth(int video_depth) +{ + return (video_depth <= VIDEO_DEPTH_8BIT) ? 8 : mac_depth_of_video_depth(video_depth); +} + // Check wether specified mode is available static bool has_mode(int type, int width, int height) { @@ -402,7 +449,7 @@ static void add_mode(int type, int width VIDEO_MODE_Y = height; VIDEO_MODE_RESOLUTION = resolution_id; VIDEO_MODE_ROW_BYTES = bytes_per_row; - VIDEO_MODE_DEPTH = depth; + VIDEO_MODE_DEPTH = (video_depth)depth; VideoModes.push_back(mode); } @@ -538,12 +585,15 @@ driver_base::~driver_base() if (s) SDL_FreeSurface(s); + // the_buffer shall always be mapped through vm_acquire_framebuffer() + if (the_buffer != VM_MAP_FAILED) { + D(bug(" releasing the_buffer at %p (%d bytes)\n", the_buffer, the_buffer_size)); + vm_release_framebuffer(the_buffer, the_buffer_size); + the_buffer = NULL; + } + // Free frame buffer(s) if (!use_vosf) { - if (the_buffer) { - free(the_buffer); - the_buffer = NULL; - } if (the_buffer_copy) { free(the_buffer_copy); the_buffer_copy = NULL; @@ -551,12 +601,6 @@ driver_base::~driver_base() } #ifdef ENABLE_VOSF else { - // the_buffer shall always be mapped through vm_acquire() so that we can vm_protect() it at will - if (the_buffer != VM_MAP_FAILED) { - D(bug(" releasing the_buffer at %p (%d bytes)\n", the_buffer, the_buffer_size)); - vm_release(the_buffer, the_buffer_size); - the_buffer = NULL; - } if (the_host_buffer) { D(bug(" freeing the_host_buffer at %p\n", the_host_buffer)); free(the_host_buffer); @@ -567,6 +611,9 @@ driver_base::~driver_base() free(the_buffer_copy); the_buffer_copy = NULL; } + + // Deinitialize VOSF + video_vosf_exit(); } #endif } @@ -576,7 +623,7 @@ void driver_base::update_palette(void) { const VIDEO_MODE &mode = monitor.get_current_mode(); - if (VIDEO_MODE_DEPTH <= VIDEO_DEPTH_8BIT) + if ((int)VIDEO_MODE_DEPTH <= VIDEO_DEPTH_8BIT) SDL_SetPalette(s, SDL_PHYSPAL, sdl_palette, 0, 256); } @@ -607,7 +654,7 @@ driver_window::driver_window(SDL_monitor ADBSetRelMouseMode(mouse_grabbed); // Create surface - int depth = (VIDEO_MODE_DEPTH <= VIDEO_DEPTH_8BIT ? 8 : screen_depth); + int depth = sdl_depth_of_video_depth(VIDEO_MODE_DEPTH); if ((s = SDL_SetVideoMode(width, height, depth, SDL_HWSURFACE)) == NULL) return; @@ -616,23 +663,48 @@ driver_window::driver_window(SDL_monitor // Allocate memory for frame buffer (SIZE is extended to page-boundary) the_host_buffer = (uint8 *)s->pixels; the_buffer_size = page_extend((aligned_height + 2) * s->pitch); - the_buffer = (uint8 *)vm_acquire(the_buffer_size); + the_buffer = (uint8 *)vm_acquire_framebuffer(the_buffer_size); the_buffer_copy = (uint8 *)malloc(the_buffer_size); D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer)); + + // Check whether we can initialize the VOSF subsystem and it's profitable + if (!video_vosf_init(m)) { + WarningAlert(STR_VOSF_INIT_ERR); + use_vosf = false; + } + else if (!video_vosf_profitable()) { + video_vosf_exit(); + printf("VOSF acceleration is not profitable on this platform, disabling it\n"); + use_vosf = false; + } + if (!use_vosf) { + free(the_buffer_copy); + vm_release(the_buffer, the_buffer_size); + the_host_buffer = NULL; + } +#endif + if (!use_vosf) { + // Allocate memory for frame buffer + the_buffer_size = (aligned_height + 2) * s->pitch; + the_buffer_copy = (uint8 *)calloc(1, the_buffer_size); + the_buffer = (uint8 *)vm_acquire_framebuffer(the_buffer_size); + D(bug("the_buffer = %p, the_buffer_copy = %p\n", the_buffer, the_buffer_copy)); + } + +#ifdef SHEEPSHAVER + // Create cursor + if ((sdl_cursor = SDL_CreateCursor(MacCursor + 4, MacCursor + 36, 16, 16, 0, 0)) != NULL) { + SDL_SetCursor(sdl_cursor); + cursor_changed = false; + } #else - // Allocate memory for frame buffer - the_buffer_size = (aligned_height + 2) * s->pitch; - the_buffer_copy = (uint8 *)calloc(1, the_buffer_size); - the_buffer = (uint8 *)calloc(1, the_buffer_size); - D(bug("the_buffer = %p, the_buffer_copy = %p\n", the_buffer, the_buffer_copy)); + // Hide cursor + SDL_ShowCursor(0); #endif // Set window name/class set_window_name(STR_WINDOW_TITLE); - // Hide cursor - SDL_ShowCursor(0); - // Init blitting routines SDL_PixelFormat *f = s->format; VisualFormat visualFormat; @@ -640,7 +712,7 @@ driver_window::driver_window(SDL_monitor visualFormat.Rmask = f->Rmask; visualFormat.Gmask = f->Gmask; visualFormat.Bmask = f->Bmask; - Screen_blitter_init(visualFormat, true, sdl_depth_of_video_depth(VIDEO_MODE_DEPTH)); + Screen_blitter_init(visualFormat, true, mac_depth_of_video_depth(VIDEO_MODE_DEPTH)); // Load gray ramp to 8->16/32 expand map if (!IsDirectMode(mode)) @@ -738,6 +810,7 @@ static void keycode_init(void) SDL_VideoDriverName(video_driver, sizeof(video_driver)); bool video_driver_found = false; char line[256]; + int n_keys = 0; while (fgets(line, sizeof(line) - 1, f)) { // Read line int len = strlen(line); @@ -750,22 +823,23 @@ static void keycode_init(void) continue; if (video_driver_found) { - // Skip aliases - static const char alias_str[] = "alias"; - if (strncmp(line, alias_str, sizeof(alias_str) - 1) == 0) + // Skip aliases as long as we have read keycodes yet + // Otherwise, it's another mapping and we have to stop + static const char sdl_str[] = "sdl"; + if (strncmp(line, sdl_str, sizeof(sdl_str) - 1) == 0 && n_keys == 0) continue; // Read keycode int x_code, mac_code; if (sscanf(line, "%d %d", &x_code, &mac_code) == 2) - keycode_table[x_code & 0xff] = mac_code; + keycode_table[x_code & 0xff] = mac_code, n_keys++; else break; } else { // Search for SDL video driver string - static const char alias_sdl_str[] = "alias SDL"; - if (strncmp(line, alias_sdl_str, sizeof(alias_sdl_str) - 1) == 0) { - char *p = line + sizeof(alias_sdl_str); + static const char sdl_str[] = "sdl"; + if (strncmp(line, sdl_str, sizeof(sdl_str) - 1) == 0) { + char *p = line + sizeof(sdl_str); if (strstr(video_driver, p) == video_driver) video_driver_found = true; } @@ -783,6 +857,8 @@ static void keycode_init(void) WarningAlert(str); return; } + + D(bug("Using SDL/%s keycodes table, %d key mappings\n", video_driver, n_keys)); } } @@ -810,16 +886,6 @@ bool SDL_monitor_desc::video_open(void) return false; } -#ifdef ENABLE_VOSF - if (use_vosf) { - // Initialize the VOSF system - if (!video_vosf_init(*this)) { - ErrorAlert(STR_VOSF_INIT_ERR); - return false; - } - } -#endif - // Initialize VideoRefresh function VideoRefreshInit(); @@ -929,7 +995,7 @@ bool VideoInit(bool classic) add_mode(display_type, 512, 342, 0x80, 64, VIDEO_DEPTH_1BIT); else { for (int d = VIDEO_DEPTH_1BIT; d <= default_depth; d++) { - int bpp = (d <= VIDEO_DEPTH_8BIT ? 8 : sdl_depth_of_video_depth(d)); + int bpp = sdl_depth_of_video_depth(d); if (SDL_VideoModeOK(max_width, max_height, bpp, SDL_HWSURFACE)) add_window_modes(video_depth(d)); } @@ -1017,13 +1083,6 @@ void SDL_monitor_desc::video_close(void) UNLOCK_FRAME_BUFFER; D(bug(" frame buffer unlocked\n")); -#ifdef ENABLE_VOSF - if (use_vosf) { - // Deinitialize VOSF - video_vosf_exit(); - } -#endif - // Close display delete drv; drv = NULL; @@ -1121,7 +1180,7 @@ void SDL_monitor_desc::set_palette(uint8 const VIDEO_MODE &mode = get_current_mode(); // FIXME: how can we handle the gamma ramp? - if (VIDEO_MODE_DEPTH > VIDEO_DEPTH_8BIT) + if ((int)VIDEO_MODE_DEPTH > VIDEO_DEPTH_8BIT) return; LOCK_PALETTE; @@ -1146,11 +1205,13 @@ void SDL_monitor_desc::set_palette(uint8 } #ifdef ENABLE_VOSF - // We have to redraw everything because the interpretation of pixel values changed - LOCK_VOSF; - PFLAG_SET_ALL; - UNLOCK_VOSF; - memset(the_buffer_copy, 0, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y); + if (use_vosf) { + // We have to redraw everything because the interpretation of pixel values changed + LOCK_VOSF; + PFLAG_SET_ALL; + UNLOCK_VOSF; + memset(the_buffer_copy, 0, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y); + } #endif } @@ -1180,8 +1241,11 @@ int16 video_mode_change(VidLocals *csSav csSave->saveData = ReadMacInt32(ParamPtr + csData); csSave->savePage = ReadMacInt16(ParamPtr + csPage); - // Disable interrupts + // Disable interrupts and pause redraw thread DisableInterrupt(); + thread_stop_ack = false; + thread_stop_req = true; + while (!thread_stop_ack) ; cur_mode = i; monitor_desc *monitor = VideoMonitors[0]; @@ -1192,7 +1256,8 @@ int16 video_mode_change(VidLocals *csSav csSave->saveData=VModes[cur_mode].viAppleID;/* First mode ... */ csSave->saveMode=VModes[cur_mode].viAppleMode; - // Enable interrupts + // Enable interrupts and resume redraw thread + thread_stop_req = false; EnableInterrupt(); return noErr; } @@ -1221,8 +1286,7 @@ void SDL_monitor_desc::switch_to_current #ifdef SHEEPSHAVER bool video_can_change_cursor(void) { -// return hw_mac_cursor_accl && (display_type != DISPLAY_SCREEN); - return false; + return (display_type == DISPLAY_WINDOW); } #endif @@ -1234,371 +1298,42 @@ bool video_can_change_cursor(void) #ifdef SHEEPSHAVER void video_set_cursor(void) { -// cursor_changed = true; + cursor_changed = true; } #endif /* - * Install graphics acceleration + * Keyboard-related utilify functions */ -#ifdef SHEEPSHAVER -// Rectangle inversion -template< int bpp > -static inline void do_invrect(uint8 *dest, uint32 length) +static bool is_modifier_key(SDL_KeyboardEvent const & e) { -#define INVERT_1(PTR, OFS) ((uint8 *)(PTR))[OFS] = ~((uint8 *)(PTR))[OFS] -#define INVERT_2(PTR, OFS) ((uint16 *)(PTR))[OFS] = ~((uint16 *)(PTR))[OFS] -#define INVERT_4(PTR, OFS) ((uint32 *)(PTR))[OFS] = ~((uint32 *)(PTR))[OFS] -#define INVERT_8(PTR, OFS) ((uint64 *)(PTR))[OFS] = ~((uint64 *)(PTR))[OFS] - -#ifndef UNALIGNED_PROFITABLE - // Align on 16-bit boundaries - if (bpp < 16 && (((uintptr)dest) & 1)) { - INVERT_1(dest, 0); - dest += 1; length -= 1; - } - - // Align on 32-bit boundaries - if (bpp < 32 && (((uintptr)dest) & 2)) { - INVERT_2(dest, 0); - dest += 2; length -= 2; - } -#endif - - // Invert 8-byte words - if (length >= 8) { - const int r = (length / 8) % 8; - dest += r * 8; - - int n = ((length / 8) + 7) / 8; - switch (r) { - case 0: do { - dest += 64; - INVERT_8(dest, -8); - case 7: INVERT_8(dest, -7); - case 6: INVERT_8(dest, -6); - case 5: INVERT_8(dest, -5); - case 4: INVERT_8(dest, -4); - case 3: INVERT_8(dest, -3); - case 2: INVERT_8(dest, -2); - case 1: INVERT_8(dest, -1); - } while (--n > 0); - } - } - - // 32-bit cell to invert? - if (length & 4) { - INVERT_4(dest, 0); - if (bpp <= 16) - dest += 4; - } - - // 16-bit cell to invert? - if (bpp <= 16 && (length & 2)) { - INVERT_2(dest, 0); - if (bpp <= 8) - dest += 2; - } - - // 8-bit cell to invert? - if (bpp <= 8 && (length & 1)) - INVERT_1(dest, 0); - -#undef INVERT_1 -#undef INVERT_2 -#undef INVERT_4 -#undef INVERT_8 -} - -void NQD_invrect(uint32 p) -{ - D(bug("accl_invrect %08x\n", p)); - - // Get inversion parameters - int16 dest_X = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2); - int16 dest_Y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0); - int16 width = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2); - int16 height = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0); - D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); - D(bug(" width %d, height %d, bytes_per_row %d\n", width, height, (int32)ReadMacInt32(p + acclDestRowBytes))); - - //!!?? pen_mode == 14 - - // And perform the inversion - const int bpp = bytes_per_pixel(ReadMacInt32(p + acclDestPixelSize)); - const int dest_row_bytes = (int32)ReadMacInt32(p + acclDestRowBytes); - uint8 *dest = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + (dest_Y * dest_row_bytes) + (dest_X * bpp)); - width *= bpp; - switch (bpp) { - case 1: - for (int i = 0; i < height; i++) { - do_invrect<8>(dest, width); - dest += dest_row_bytes; - } - break; - case 2: - for (int i = 0; i < height; i++) { - do_invrect<16>(dest, width); - dest += dest_row_bytes; - } - break; - case 4: - for (int i = 0; i < height; i++) { - do_invrect<32>(dest, width); - dest += dest_row_bytes; - } - break; - } -} - -// Rectangle filling -template< int bpp > -static inline void do_fillrect(uint8 *dest, uint32 color, uint32 length) -{ -#define FILL_1(PTR, OFS, VAL) ((uint8 *)(PTR))[OFS] = (VAL) -#define FILL_2(PTR, OFS, VAL) ((uint16 *)(PTR))[OFS] = (VAL) -#define FILL_4(PTR, OFS, VAL) ((uint32 *)(PTR))[OFS] = (VAL) -#define FILL_8(PTR, OFS, VAL) ((uint64 *)(PTR))[OFS] = (VAL) - -#ifndef UNALIGNED_PROFITABLE - // Align on 16-bit boundaries - if (bpp < 16 && (((uintptr)dest) & 1)) { - FILL_1(dest, 0, color); - dest += 1; length -= 1; - } - - // Align on 32-bit boundaries - if (bpp < 32 && (((uintptr)dest) & 2)) { - FILL_2(dest, 0, color); - dest += 2; length -= 2; - } -#endif - - // Fill 8-byte words - if (length >= 8) { - const uint64 c = (((uint64)color) << 32) | color; - const int r = (length / 8) % 8; - dest += r * 8; - - int n = ((length / 8) + 7) / 8; - switch (r) { - case 0: do { - dest += 64; - FILL_8(dest, -8, c); - case 7: FILL_8(dest, -7, c); - case 6: FILL_8(dest, -6, c); - case 5: FILL_8(dest, -5, c); - case 4: FILL_8(dest, -4, c); - case 3: FILL_8(dest, -3, c); - case 2: FILL_8(dest, -2, c); - case 1: FILL_8(dest, -1, c); - } while (--n > 0); - } - } - - // 32-bit cell to fill? - if (length & 4) { - FILL_4(dest, 0, color); - if (bpp <= 16) - dest += 4; - } - - // 16-bit cell to fill? - if (bpp <= 16 && (length & 2)) { - FILL_2(dest, 0, color); - if (bpp <= 8) - dest += 2; - } - - // 8-bit cell to fill? - if (bpp <= 8 && (length & 1)) - FILL_1(dest, 0, color); - -#undef FILL_1 -#undef FILL_2 -#undef FILL_4 -#undef FILL_8 -} - -void NQD_fillrect(uint32 p) -{ - D(bug("accl_fillrect %08x\n", p)); - - // Get filling parameters - int16 dest_X = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2); - int16 dest_Y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0); - int16 width = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2); - int16 height = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0); - uint32 color = htonl(ReadMacInt32(p + acclPenMode) == 8 ? ReadMacInt32(p + acclForePen) : ReadMacInt32(p + acclBackPen)); - D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); - D(bug(" width %d, height %d\n", width, height)); - D(bug(" bytes_per_row %d color %08x\n", (int32)ReadMacInt32(p + acclDestRowBytes), color)); - - // And perform the fill - const int bpp = bytes_per_pixel(ReadMacInt32(p + acclDestPixelSize)); - const int dest_row_bytes = (int32)ReadMacInt32(p + acclDestRowBytes); - uint8 *dest = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + (dest_Y * dest_row_bytes) + (dest_X * bpp)); - width *= bpp; - switch (bpp) { - case 1: - for (int i = 0; i < height; i++) { - memset(dest, color, width); - dest += dest_row_bytes; - } - break; - case 2: - for (int i = 0; i < height; i++) { - do_fillrect<16>(dest, color, width); - dest += dest_row_bytes; - } - break; - case 4: - for (int i = 0; i < height; i++) { - do_fillrect<32>(dest, color, width); - dest += dest_row_bytes; - } - break; - } -} - -bool NQD_fillrect_hook(uint32 p) -{ - D(bug("accl_fillrect_hook %08x\n", p)); - - // Check if we can accelerate this fillrect - if (ReadMacInt32(p + 0x284) != 0 && ReadMacInt32(p + acclDestPixelSize) >= 8) { - const int transfer_mode = ReadMacInt32(p + acclTransferMode); - if (transfer_mode == 8) { - // Fill - WriteMacInt32(p + acclDrawProc, NativeTVECT(NATIVE_FILLRECT)); - return true; - } - else if (transfer_mode == 10) { - // Invert - WriteMacInt32(p + acclDrawProc, NativeTVECT(NATIVE_INVRECT)); - return true; - } - } - return false; -} - -// Rectangle blitting -// TODO: optimize for VOSF and target pixmap == screen -void NQD_bitblt(uint32 p) -{ - D(bug("accl_bitblt %08x\n", p)); - - // Get blitting parameters - int16 src_X = (int16)ReadMacInt16(p + acclSrcRect + 2) - (int16)ReadMacInt16(p + acclSrcBoundsRect + 2); - int16 src_Y = (int16)ReadMacInt16(p + acclSrcRect + 0) - (int16)ReadMacInt16(p + acclSrcBoundsRect + 0); - int16 dest_X = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2); - int16 dest_Y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0); - int16 width = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2); - int16 height = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0); - D(bug(" src addr %08x, dest addr %08x\n", ReadMacInt32(p + acclSrcBaseAddr), ReadMacInt32(p + acclDestBaseAddr))); - D(bug(" src X %d, src Y %d, dest X %d, dest Y %d\n", src_X, src_Y, dest_X, dest_Y)); - D(bug(" width %d, height %d\n", width, height)); - - // And perform the blit - const int bpp = bytes_per_pixel(ReadMacInt32(p + acclSrcPixelSize)); - width *= bpp; - if ((int32)ReadMacInt32(p + acclSrcRowBytes) > 0) { - const int src_row_bytes = (int32)ReadMacInt32(p + acclSrcRowBytes); - const int dst_row_bytes = (int32)ReadMacInt32(p + acclDestRowBytes); - uint8 *src = Mac2HostAddr(ReadMacInt32(p + acclSrcBaseAddr) + (src_Y * src_row_bytes) + (src_X * bpp)); - uint8 *dst = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + (dest_Y * dst_row_bytes) + (dest_X * bpp)); - for (int i = 0; i < height; i++) { - memmove(dst, src, width); - src += src_row_bytes; - dst += dst_row_bytes; - } - } - else { - const int src_row_bytes = -(int32)ReadMacInt32(p + acclSrcRowBytes); - const int dst_row_bytes = -(int32)ReadMacInt32(p + acclDestRowBytes); - uint8 *src = Mac2HostAddr(ReadMacInt32(p + acclSrcBaseAddr) + ((src_Y + height - 1) * src_row_bytes) + (src_X * bpp)); - uint8 *dst = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + ((dest_Y + height - 1) * dst_row_bytes) + (dest_X * bpp)); - for (int i = height - 1; i >= 0; i--) { - memmove(dst, src, width); - src -= src_row_bytes; - dst -= dst_row_bytes; - } - } -} - -/* - BitBlt transfer modes: - 0 : srcCopy - 1 : srcOr - 2 : srcXor - 3 : srcBic - 4 : notSrcCopy - 5 : notSrcOr - 6 : notSrcXor - 7 : notSrcBic - 32 : blend - 33 : addPin - 34 : addOver - 35 : subPin - 36 : transparent - 37 : adMax - 38 : subOver - 39 : adMin - 50 : hilite -*/ - -bool NQD_bitblt_hook(uint32 p) -{ - D(bug("accl_draw_hook %08x\n", p)); - - // Check if we can accelerate this bitblt - if (ReadMacInt32(p + 0x018) + ReadMacInt32(p + 0x128) == 0 && - ReadMacInt32(p + 0x130) == 0 && - ReadMacInt32(p + acclSrcPixelSize) >= 8 && - ReadMacInt32(p + acclSrcPixelSize) == ReadMacInt32(p + acclDestPixelSize) && - (ReadMacInt32(p + acclSrcRowBytes) ^ ReadMacInt32(p + acclDestRowBytes)) >= 0 && // same sign? - ReadMacInt32(p + acclTransferMode) == 0 && // srcCopy? - ReadMacInt32(p + 0x15c) > 0) { - - // Yes, set function pointer - WriteMacInt32(p + acclDrawProc, NativeTVECT(NATIVE_BITBLT)); + switch (e.keysym.sym) { + case SDLK_NUMLOCK: + case SDLK_CAPSLOCK: + case SDLK_SCROLLOCK: + case SDLK_RSHIFT: + case SDLK_LSHIFT: + case SDLK_RCTRL: + case SDLK_LCTRL: + case SDLK_RALT: + case SDLK_LALT: + case SDLK_RMETA: + case SDLK_LMETA: + case SDLK_LSUPER: + case SDLK_RSUPER: + case SDLK_MODE: + case SDLK_COMPOSE: return true; } return false; } -// Wait for graphics operation to finish -bool NQD_sync_hook(uint32 arg) -{ - D(bug("accl_sync_hook %08x\n", arg)); - return true; -} - -void VideoInstallAccel(void) +static bool is_ctrl_down(SDL_keysym const & ks) { - // Install acceleration hooks - if (PrefsFindBool("gfxaccel")) { - D(bug("Video: Installing acceleration hooks\n")); - uint32 base; - - SheepVar bitblt_hook_info(sizeof(accl_hook_info)); - base = bitblt_hook_info.addr(); - WriteMacInt32(base + 0, NativeTVECT(NATIVE_BITBLT_HOOK)); - WriteMacInt32(base + 4, NativeTVECT(NATIVE_SYNC_HOOK)); - WriteMacInt32(base + 8, ACCL_BITBLT); - NQDMisc(6, bitblt_hook_info.ptr()); - - SheepVar fillrect_hook_info(sizeof(accl_hook_info)); - base = fillrect_hook_info.addr(); - WriteMacInt32(base + 0, NativeTVECT(NATIVE_FILLRECT_HOOK)); - WriteMacInt32(base + 4, NativeTVECT(NATIVE_SYNC_HOOK)); - WriteMacInt32(base + 8, ACCL_FILLRECT); - NQDMisc(6, fillrect_hook_info.ptr()); - } + return ctrl_down || (ks.mod & KMOD_CTRL); } -#endif /* @@ -1606,11 +1341,6 @@ void VideoInstallAccel(void) * and -2 if the key was recognized as a hotkey */ -static bool is_ctrl_down(SDL_keysym const & ks) -{ - return ctrl_down || (ks.mod & KMOD_CTRL); -} - static int kc_decode(SDL_keysym const & ks, bool key_down) { switch (ks.sym) { @@ -1680,10 +1410,17 @@ static int kc_decode(SDL_keysym const & case SDLK_RCTRL: return 0x36; case SDLK_LSHIFT: return 0x38; case SDLK_RSHIFT: return 0x38; +#if (defined(__APPLE__) && defined(__MACH__)) + case SDLK_LALT: return 0x3a; + case SDLK_RALT: return 0x3a; + case SDLK_LMETA: return 0x37; + case SDLK_RMETA: return 0x37; +#else case SDLK_LALT: return 0x37; case SDLK_RALT: return 0x37; case SDLK_LMETA: return 0x3a; case SDLK_RMETA: return 0x3a; +#endif case SDLK_MENU: return 0x32; case SDLK_CAPSLOCK: return 0x39; case SDLK_NUMLOCK: return 0x47; @@ -1790,7 +1527,7 @@ static void handle_events(void) // Keyboard case SDL_KEYDOWN: { int code = -1; - if (use_keycodes) { + if (use_keycodes && !is_modifier_key(event.key)) { if (event2keycode(event.key, true) != -2) // This is called to process the hotkeys code = keycode_table[event.key.keysym.scancode & 0xff]; } else @@ -1818,13 +1555,22 @@ static void handle_events(void) } case SDL_KEYUP: { int code = -1; - if (use_keycodes) { + if (use_keycodes && !is_modifier_key(event.key)) { if (event2keycode(event.key, false) != -2) // This is called to process the hotkeys code = keycode_table[event.key.keysym.scancode & 0xff]; } else code = event2keycode(event.key, false); - if (code >= 0 && code != 0x39) { // Don't propagate Caps Lock releases - ADBKeyUp(code); + if (code >= 0) { + if (code == 0x39) { // Caps Lock released + if (caps_on) { + ADBKeyUp(code); + caps_on = false; + } else { + ADBKeyDown(code); + caps_on = true; + } + } else + ADBKeyUp(code); if (code == 0x36) ctrl_down = false; } @@ -1891,7 +1637,7 @@ static void update_display_static(driver // Check for first column from left and first column from right that have changed if (high) { - if (VIDEO_MODE_DEPTH < VIDEO_DEPTH_8BIT) { + if ((int)VIDEO_MODE_DEPTH < VIDEO_DEPTH_8BIT) { const int src_bytes_per_row = bytes_per_row; const int dst_bytes_per_row = drv->s->pitch; const int pixels_per_byte = VIDEO_MODE_X / src_bytes_per_row; @@ -2152,12 +1898,31 @@ static int redraw_func(void *arg) next = GetTicks_usec(); ticks++; +#ifdef SHEEPSHAVER + // Pause if requested (during video mode switches) + if (thread_stop_req) { + thread_stop_ack = true; + continue; + } +#endif + // Handle SDL events handle_events(); // Refresh display video_refresh(); +#ifdef SHEEPSHAVER + // Set new cursor image if it was changed + if (cursor_changed && sdl_cursor) { + cursor_changed = false; + SDL_FreeCursor(sdl_cursor); + sdl_cursor = SDL_CreateCursor(MacCursor + 4, MacCursor + 36, 16, 16, MacCursor[2], MacCursor[3]); + if (sdl_cursor) + SDL_SetCursor(sdl_cursor); + } +#endif + // Set new palette if it was changed handle_palette_changes(); }