ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/SDL/video_sdl.cpp
(Generate patch)

Comparing BasiliskII/src/SDL/video_sdl.cpp (file contents):
Revision 1.1 by gbeauche, 2004-06-23T13:47:20Z vs.
Revision 1.6 by gbeauche, 2004-06-24T22:38:42Z

# Line 32 | Line 32
32   *  - Force relative mode in Grab mode even if SDL provides absolute coordinates?
33   *  - Fullscreen mode
34   *  - Gamma tables support is likely to be broken here
35 + *  - Events processing is bound to the general emulation thread as SDL requires
36 + *    to PumpEvents() within the same thread as the one that called SetVideoMode().
37 + *    Besides, there can't seem to be a way to call SetVideoMode() from a child thread.
38 + *  - Refresh performance is still slow. Use SDL_CreateRGBSurface()?
39 + *  - Backport hw cursor acceleration to Basilisk II?
40 + *  - Move generic Native QuickDraw acceleration routines to gfxaccel.cpp
41   */
42  
43   #include "sysdeps.h"
# Line 40 | Line 46
46   #include <SDL_mutex.h>
47   #include <SDL_thread.h>
48   #include <errno.h>
49 + #include <vector>
50  
51   #include "cpu_emulation.h"
52   #include "main.h"
# Line 48 | Line 55
55   #include "prefs.h"
56   #include "user_strings.h"
57   #include "video.h"
58 + #include "video_defs.h"
59   #include "video_blit.h"
60  
61   #define DEBUG 0
# Line 55 | Line 63
63  
64  
65   // Supported video modes
66 < static vector<video_mode> VideoModes;
66 > using std::vector;
67 > static vector<VIDEO_MODE> VideoModes;
68  
69   // Display types
70 + #ifdef SHEEPSHAVER
71   enum {
72 <        DISPLAY_WINDOW, // windowed display
73 <        DISPLAY_SCREEN  // fullscreen display
72 >        DISPLAY_WINDOW = DIS_WINDOW,                                    // windowed display
73 >        DISPLAY_SCREEN = DIS_SCREEN                                             // fullscreen display
74   };
75 + extern int display_type;                                                        // See enum above
76 + #else
77 + enum {
78 +        DISPLAY_WINDOW,                                                                 // windowed display
79 +        DISPLAY_SCREEN                                                                  // fullscreen display
80 + };
81 + static int display_type = DISPLAY_WINDOW;                       // See enum above
82 + #endif
83  
84   // Constants
85   const char KEYCODE_FILE_NAME[] = DATADIR "/keycodes";
# Line 72 | Line 90 | static int32 frame_skip;                                                       // Prefs
90   static int16 mouse_wheel_mode;
91   static int16 mouse_wheel_lines;
92  
75 static int display_type = DISPLAY_WINDOW;                       // See enum above
93   static uint8 *the_buffer = NULL;                                        // Mac frame buffer (where MacOS draws into)
94   static uint8 *the_buffer_copy = NULL;                           // Copy of Mac frame buffer (for refreshed modes)
95   static uint32 the_buffer_size;                                          // Size of allocated the_buffer
# Line 100 | Line 117 | static int keycode_table[256];                                         // X
117  
118   // SDL variables
119   static int screen_depth;                                                        // Depth of current screen
120 + static SDL_Cursor *sdl_cursor;                                          // Copy of Mac cursor
121 + static volatile bool cursor_changed = false;            // Flag: cursor changed, redraw_func must update the cursor
122   static SDL_Color sdl_palette[256];                                      // Color palette to be used as CLUT and gamma table
123   static bool sdl_palette_changed = false;                        // Flag: Palette changed, redraw thread must set new colors
124 + static const int sdl_eventmask = SDL_MOUSEBUTTONDOWNMASK | SDL_MOUSEBUTTONUPMASK | SDL_MOUSEMOTIONMASK | SDL_KEYUPMASK | SDL_KEYDOWNMASK | SDL_VIDEOEXPOSEMASK | SDL_QUITMASK;
125  
126   // Mutex to protect palette
127   static SDL_mutex *sdl_palette_lock = NULL;
# Line 126 | Line 146 | extern void SysMountFirstFloppy(void);
146  
147  
148   /*
149 + *  SheepShaver glue
150 + */
151 +
152 + #ifdef SHEEPSHAVER
153 + // Color depth modes type
154 + typedef int video_depth;
155 +
156 + // 1, 2, 4 and 8 bit depths use a color palette
157 + static inline bool IsDirectMode(VIDEO_MODE const & mode)
158 + {
159 +        return IsDirectMode(mode.viAppleMode);
160 + }
161 +
162 + // Abstract base class representing one (possibly virtual) monitor
163 + // ("monitor" = rectangular display with a contiguous frame buffer)
164 + class monitor_desc {
165 + public:
166 +        monitor_desc(const vector<VIDEO_MODE> &available_modes, video_depth default_depth, uint32 default_id) {}
167 +        virtual ~monitor_desc() {}
168 +
169 +        // Get current Mac frame buffer base address
170 +        uint32 get_mac_frame_base(void) const {return screen_base;}
171 +
172 +        // Set Mac frame buffer base address (called from switch_to_mode())
173 +        void set_mac_frame_base(uint32 base) {screen_base = base;}
174 +
175 +        // Get current video mode
176 +        const VIDEO_MODE &get_current_mode(void) const {return VModes[cur_mode];}
177 +
178 +        // Called by the video driver to switch the video mode on this display
179 +        // (must call set_mac_frame_base())
180 +        virtual void switch_to_current_mode(void) = 0;
181 +
182 +        // Called by the video driver to set the color palette (in indexed modes)
183 +        // or the gamma table (in direct modes)
184 +        virtual void set_palette(uint8 *pal, int num) = 0;
185 + };
186 +
187 + // Vector of pointers to available monitor descriptions, filled by VideoInit()
188 + static vector<monitor_desc *> VideoMonitors;
189 +
190 + // Find Apple mode matching best specified dimensions
191 + static int find_apple_resolution(int xsize, int ysize)
192 + {
193 +        int apple_id;
194 +        if (xsize < 800)
195 +                apple_id = APPLE_640x480;
196 +        else if (xsize < 1024)
197 +                apple_id = APPLE_800x600;
198 +        else if (xsize < 1152)
199 +                apple_id = APPLE_1024x768;
200 +        else if (xsize < 1280) {
201 +                if (ysize < 900)
202 +                        apple_id = APPLE_1152x768;
203 +                else
204 +                        apple_id = APPLE_1152x900;
205 +        }
206 +        else if (xsize < 1600)
207 +                apple_id = APPLE_1280x1024;
208 +        else
209 +                apple_id = APPLE_1600x1200;
210 +        return apple_id;
211 + }
212 +
213 + // Set parameters to specified Apple mode
214 + static void set_apple_resolution(int apple_id, int &xsize, int &ysize)
215 + {
216 +        switch (apple_id) {
217 +        case APPLE_640x480:
218 +                xsize = 640;
219 +                ysize = 480;
220 +                break;
221 +        case APPLE_800x600:
222 +                xsize = 800;
223 +                ysize = 600;
224 +                break;
225 +        case APPLE_1024x768:
226 +                xsize = 1024;
227 +                ysize = 768;
228 +                break;
229 +        case APPLE_1152x768:
230 +                xsize = 1152;
231 +                ysize = 768;
232 +                break;
233 +        case APPLE_1152x900:
234 +                xsize = 1152;
235 +                ysize = 900;
236 +                break;
237 +        case APPLE_1280x1024:
238 +                xsize = 1280;
239 +                ysize = 1024;
240 +                break;
241 +        case APPLE_1600x1200:
242 +                xsize = 1600;
243 +                ysize = 1200;
244 +                break;
245 +        default:
246 +                abort();
247 +        }
248 + }
249 +
250 + // Match Apple mode matching best specified dimensions
251 + static int match_apple_resolution(int &xsize, int &ysize)
252 + {
253 +        int apple_id = find_apple_resolution(xsize, ysize);
254 +        set_apple_resolution(apple_id, xsize, ysize);
255 +        return apple_id;
256 + }
257 +
258 + // Display error alert
259 + static void ErrorAlert(int error)
260 + {
261 +        ErrorAlert(GetString(error));
262 + }
263 + #endif
264 +
265 +
266 + /*
267   *  monitor_desc subclass for SDL display
268   */
269  
270   class SDL_monitor_desc : public monitor_desc {
271   public:
272 <        SDL_monitor_desc(const vector<video_mode> &available_modes, video_depth default_depth, uint32 default_id) : monitor_desc(available_modes, default_depth, default_id) {}
272 >        SDL_monitor_desc(const vector<VIDEO_MODE> &available_modes, video_depth default_depth, uint32 default_id) : monitor_desc(available_modes, default_depth, default_id) {}
273          ~SDL_monitor_desc() {}
274  
275          virtual void switch_to_current_mode(void);
# Line 146 | Line 284 | public:
284   *  Utility functions
285   */
286  
287 + // Find palette size for given color depth
288 + static int palette_size(int mode)
289 + {
290 +        switch (mode) {
291 +        case VIDEO_DEPTH_1BIT: return 2;
292 +        case VIDEO_DEPTH_2BIT: return 4;
293 +        case VIDEO_DEPTH_4BIT: return 16;
294 +        case VIDEO_DEPTH_8BIT: return 256;
295 +        case VIDEO_DEPTH_16BIT: return 32;
296 +        case VIDEO_DEPTH_32BIT: return 256;
297 +        default: return 0;
298 +        }
299 + }
300 +
301 + // Return bytes per pixel for requested depth
302 + static inline int bytes_per_pixel(int depth)
303 + {
304 +        int bpp;
305 +        switch (depth) {
306 +        case 8:
307 +                bpp = 1;
308 +                break;
309 +        case 15: case 16:
310 +                bpp = 2;
311 +                break;
312 +        case 24: case 32:
313 +                bpp = 4;
314 +                break;
315 +        default:
316 +                abort();
317 +        }
318 +        return bpp;
319 + }
320 +
321   // Map video_mode depth ID to numerical depth value
322   static int sdl_depth_of_video_depth(int video_depth)
323   {
324          int depth = -1;
325          switch (video_depth) {
326 <        case VDEPTH_1BIT:
326 >        case VIDEO_DEPTH_1BIT:
327                  depth = 1;
328                  break;
329 <        case VDEPTH_2BIT:
329 >        case VIDEO_DEPTH_2BIT:
330                  depth = 2;
331                  break;
332 <        case VDEPTH_4BIT:
332 >        case VIDEO_DEPTH_4BIT:
333                  depth = 4;
334                  break;
335 <        case VDEPTH_8BIT:
335 >        case VIDEO_DEPTH_8BIT:
336                  depth = 8;
337                  break;
338 <        case VDEPTH_16BIT:
338 >        case VIDEO_DEPTH_16BIT:
339                  depth = 16;
340                  break;
341 <        case VDEPTH_32BIT:
341 >        case VIDEO_DEPTH_32BIT:
342                  depth = 32;
343                  break;
344          default:
# Line 175 | Line 347 | static int sdl_depth_of_video_depth(int
347          return depth;
348   }
349  
350 + // Check wether specified mode is available
351 + static bool has_mode(int type, int width, int height)
352 + {
353 +        // FIXME: no fullscreen support yet
354 +        if (type == DISPLAY_SCREEN)
355 +                return false;
356 +
357 + #ifdef SHEEPSHAVER
358 +        // Filter out Classic resolutiosn
359 +        if (width == 512 && height == 384)
360 +                return false;
361 +
362 +        // Read window modes prefs
363 +        static uint32 window_modes = 0;
364 +        static uint32 screen_modes = 0;
365 +        if (window_modes == 0 || screen_modes == 0) {
366 +                window_modes = PrefsFindInt32("windowmodes");
367 +                screen_modes = PrefsFindInt32("screenmodes");
368 +                if (window_modes == 0 || screen_modes == 0)
369 +                        window_modes |= 3;                      // Allow at least 640x480 and 800x600 window modes
370 +        }
371 +
372 +        if (type == DISPLAY_WINDOW) {
373 +                int apple_mask, apple_id = find_apple_resolution(width, height);
374 +                switch (apple_id) {
375 +                case APPLE_640x480:             apple_mask = 0x01; break;
376 +                case APPLE_800x600:             apple_mask = 0x02; break;
377 +                case APPLE_1024x768:    apple_mask = 0x04; break;
378 +                case APPLE_1152x768:    apple_mask = 0x40; break;
379 +                case APPLE_1152x900:    apple_mask = 0x08; break;
380 +                case APPLE_1280x1024:   apple_mask = 0x10; break;
381 +                case APPLE_1600x1200:   apple_mask = 0x20; break;
382 +                default:                                apple_mask = 0x00; break;
383 +                }
384 +                return (window_modes & apple_mask);
385 +        }
386 + #else
387 +        return true;
388 + #endif
389 +        return false;
390 + }
391 +
392   // Add mode to list of supported modes
393 < static void add_mode(uint32 width, uint32 height, uint32 resolution_id, uint32 bytes_per_row, video_depth depth)
393 > static void add_mode(int type, int width, int height, int resolution_id, int bytes_per_row, int depth)
394   {
395 <        video_mode mode;
396 <        mode.x = width;
397 <        mode.y = height;
398 <        mode.resolution_id = resolution_id;
399 <        mode.bytes_per_row = bytes_per_row;
400 <        mode.depth = depth;
395 >        // Filter out unsupported modes
396 >        if (!has_mode(type, width, height))
397 >                return;
398 >
399 >        // Fill in VideoMode entry
400 >        VIDEO_MODE mode;
401 > #ifdef SHEEPSHAVER
402 >        // Recalculate dimensions to fit Apple modes
403 >        resolution_id = match_apple_resolution(width, height);
404 >        mode.viType = type;
405 > #endif
406 >        VIDEO_MODE_X = width;
407 >        VIDEO_MODE_Y = height;
408 >        VIDEO_MODE_RESOLUTION = resolution_id;
409 >        VIDEO_MODE_ROW_BYTES = bytes_per_row;
410 >        VIDEO_MODE_DEPTH = depth;
411          VideoModes.push_back(mode);
412   }
413  
414   // Add standard list of windowed modes for given color depth
415 < static void add_window_modes(video_depth depth)
415 > static void add_window_modes(int depth)
416   {
417 <        add_mode(512, 384, 0x80, TrivialBytesPerRow(512, depth), depth);
418 <        add_mode(640, 480, 0x81, TrivialBytesPerRow(640, depth), depth);
419 <        add_mode(800, 600, 0x82, TrivialBytesPerRow(800, depth), depth);
420 <        add_mode(1024, 768, 0x83, TrivialBytesPerRow(1024, depth), depth);
421 <        add_mode(1152, 870, 0x84, TrivialBytesPerRow(1152, depth), depth);
422 <        add_mode(1280, 1024, 0x85, TrivialBytesPerRow(1280, depth), depth);
423 <        add_mode(1600, 1200, 0x86, TrivialBytesPerRow(1600, depth), depth);
417 >        video_depth vdepth = (video_depth)depth;
418 >        add_mode(DISPLAY_WINDOW, 512, 384, 0x80, TrivialBytesPerRow(512, vdepth), depth);
419 >        add_mode(DISPLAY_WINDOW, 640, 480, 0x81, TrivialBytesPerRow(640, vdepth), depth);
420 >        add_mode(DISPLAY_WINDOW, 800, 600, 0x82, TrivialBytesPerRow(800, vdepth), depth);
421 >        add_mode(DISPLAY_WINDOW, 1024, 768, 0x83, TrivialBytesPerRow(1024, vdepth), depth);
422 >        add_mode(DISPLAY_WINDOW, 1152, 870, 0x84, TrivialBytesPerRow(1152, vdepth), depth);
423 >        add_mode(DISPLAY_WINDOW, 1280, 1024, 0x85, TrivialBytesPerRow(1280, vdepth), depth);
424 >        add_mode(DISPLAY_WINDOW, 1600, 1200, 0x86, TrivialBytesPerRow(1600, vdepth), depth);
425   }
426  
427   // Set Mac frame layout and base address (uses the_buffer/MacFrameBaseMac)
428 < static void set_mac_frame_buffer(SDL_monitor_desc &monitor, video_depth depth, bool native_byte_order)
428 > static void set_mac_frame_buffer(SDL_monitor_desc &monitor, int depth, bool native_byte_order)
429   {
430   #if !REAL_ADDRESSING && !DIRECT_ADDRESSING
431          int layout = FLAYOUT_DIRECT;
432 <        if (depth == VDEPTH_16BIT)
432 >        if (depth == VIDEO_DEPTH_16BIT)
433                  layout = (screen_depth == 15) ? FLAYOUT_HOST_555 : FLAYOUT_HOST_565;
434 <        else if (depth == VDEPTH_32BIT)
434 >        else if (depth == VIDEO_DEPTH_32BIT)
435                  layout = (screen_depth == 24) ? FLAYOUT_HOST_888 : FLAYOUT_DIRECT;
436          if (native_byte_order)
437                  MacFrameLayout = layout;
# Line 215 | Line 440 | static void set_mac_frame_buffer(SDL_mon
440          monitor.set_mac_frame_base(MacFrameBaseMac);
441  
442          // Set variables used by UAE memory banking
443 <        const video_mode &mode = monitor.get_current_mode();
443 >        const VIDEO_MODE &mode = monitor.get_current_mode();
444          MacFrameBaseHost = the_buffer;
445 <        MacFrameSize = mode.bytes_per_row * mode.y;
445 >        MacFrameSize = VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y;
446          InitFrameBufferMapping();
447   #else
448          monitor.set_mac_frame_base(Host2MacAddr(the_buffer));
# Line 266 | Line 491 | public:
491  
492   public:
493          SDL_monitor_desc &monitor; // Associated video monitor
494 <        const video_mode &mode;    // Video mode handled by the driver
494 >        const VIDEO_MODE &mode;    // Video mode handled by the driver
495  
496          bool init_ok;   // Initialization succeeded (we can't use exceptions because of -fomit-frame-pointer)
497          SDL_Surface *s; // The surface we draw into
# Line 354 | Line 579 | driver_base::~driver_base()
579   // Palette has changed
580   void driver_base::update_palette(void)
581   {
582 <        const video_mode &mode = monitor.get_current_mode();
582 >        const VIDEO_MODE &mode = monitor.get_current_mode();
583  
584 <        if (mode.depth <= VDEPTH_8BIT)
584 >        if (VIDEO_MODE_DEPTH <= VIDEO_DEPTH_8BIT)
585                  SDL_SetPalette(s, SDL_PHYSPAL, sdl_palette, 0, 256);
586   }
587  
# Line 379 | Line 604 | void driver_base::restore_mouse_accel(vo
604   driver_window::driver_window(SDL_monitor_desc &m)
605          : driver_base(m), mouse_grabbed(false)
606   {
607 <        int width = mode.x, height = mode.y;
607 >        int width = VIDEO_MODE_X, height = VIDEO_MODE_Y;
608          int aligned_width = (width + 15) & ~15;
609          int aligned_height = (height + 15) & ~15;
610  
# Line 387 | Line 612 | driver_window::driver_window(SDL_monitor
612          ADBSetRelMouseMode(mouse_grabbed);
613  
614          // Create surface
615 <        int depth = (mode.depth <= VDEPTH_8BIT ? 8 : screen_depth);
615 >        int depth = (VIDEO_MODE_DEPTH <= VIDEO_DEPTH_8BIT ? 8 : screen_depth);
616          if ((s = SDL_SetVideoMode(width, height, depth, SDL_HWSURFACE)) == NULL)
617                  return;
618  
# Line 407 | Line 632 | driver_window::driver_window(SDL_monitor
632          D(bug("the_buffer = %p, the_buffer_copy = %p\n", the_buffer, the_buffer_copy));
633   #endif
634  
635 <        // Set window name/class
636 <        set_window_name(STR_WINDOW_TITLE);
637 <
635 > #ifdef SHEEPSHAVER
636 >        // Create cursor
637 >        if ((sdl_cursor = SDL_CreateCursor(MacCursor + 4, MacCursor + 36, 16, 16, 0, 0)) != NULL) {
638 >                SDL_SetCursor(sdl_cursor);
639 >                cursor_changed = false;
640 >        }
641 > #else
642          // Hide cursor
643          SDL_ShowCursor(0);
644 + #endif
645 +
646 +        // Set window name/class
647 +        set_window_name(STR_WINDOW_TITLE);
648  
649          // Init blitting routines
650          SDL_PixelFormat *f = s->format;
# Line 420 | Line 653 | driver_window::driver_window(SDL_monitor
653          visualFormat.Rmask = f->Rmask;
654          visualFormat.Gmask = f->Gmask;
655          visualFormat.Bmask = f->Bmask;
656 <        Screen_blitter_init(visualFormat, true, sdl_depth_of_video_depth(mode.depth));
656 >        Screen_blitter_init(visualFormat, true, sdl_depth_of_video_depth(VIDEO_MODE_DEPTH));
657  
658          // Load gray ramp to 8->16/32 expand map
659          if (!IsDirectMode(mode))
# Line 428 | Line 661 | driver_window::driver_window(SDL_monitor
661                          ExpandMap[i] = SDL_MapRGB(f, i, i, i);
662  
663          // Set frame buffer base
664 <        set_mac_frame_buffer(monitor, mode.depth, true);
664 >        set_mac_frame_buffer(monitor, VIDEO_MODE_DEPTH, true);
665  
666          // Everything went well
667          init_ok = true;
# Line 570 | Line 803 | static void keycode_init(void)
803   bool SDL_monitor_desc::video_open(void)
804   {
805          D(bug("video_open()\n"));
806 <        const video_mode &mode = get_current_mode();
806 >        const VIDEO_MODE &mode = get_current_mode();
807 > #if DEBUG
808 >        D(bug("Current video mode:\n"));
809 >        D(bug(" %dx%d (ID %02x), %d bpp\n", VIDEO_MODE_X, VIDEO_MODE_Y, VIDEO_MODE_RESOLUTION, 1 << (VIDEO_MODE_DEPTH & 0x0f)));
810 > #endif
811  
812          // Create display driver object of requested type
813          switch (display_type) {
# Line 604 | Line 841 | bool SDL_monitor_desc::video_open(void)
841  
842          // Start redraw/input thread
843          redraw_thread_cancel = false;
844 <        redraw_thread_active = (SDL_CreateThread(redraw_func, NULL) != NULL);
844 >        redraw_thread_active = ((redraw_thread = SDL_CreateThread(redraw_func, NULL)) != NULL);
845          if (!redraw_thread_active) {
846                  printf("FATAL: cannot create redraw thread\n");
847                  return false;
# Line 612 | Line 849 | bool SDL_monitor_desc::video_open(void)
849          return true;
850   }
851  
852 + #ifdef SHEEPSHAVER
853 + bool VideoInit(void)
854 + {
855 +        const bool classic = false;
856 + #else
857   bool VideoInit(bool classic)
858   {
859 + #endif
860          classic_mode = classic;
861  
862   #ifdef ENABLE_VOSF
# Line 637 | Line 880 | bool VideoInit(bool classic)
880          mouse_wheel_lines = PrefsFindInt32("mousewheellines");
881  
882          // Get screen mode from preferences
883 <        const char *mode_str;
883 >        const char *mode_str = NULL;
884 > #ifndef SHEEPSHAVER
885          if (classic_mode)
886                  mode_str = "win/512/342";
887          else
888                  mode_str = PrefsFindString("screen");
889 + #endif
890  
891          // Determine display type and default dimensions
892 <        int default_width = 512, default_height = 384;
892 >        int default_width, default_height;
893 >        if (classic) {
894 >                default_width = 512;
895 >                default_height = 384;
896 >        }
897 >        else {
898 >                default_width = 640;
899 >                default_height = 480;
900 >        }
901          display_type = DISPLAY_WINDOW;
902          if (mode_str) {
903                  if (sscanf(mode_str, "win/%d/%d", &default_width, &default_height) == 2)
904                          display_type = DISPLAY_WINDOW;
905          }
906          int max_width = 640, max_height = 480;
907 <        if (display_type == DISPLAY_SCREEN) {
908 <                SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
909 <                if (modes && modes != (SDL_Rect **)-1) {
910 <                        max_width = modes[0]->w;
911 <                        max_height = modes[0]->h;
912 <                }
907 >        SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
908 >        if (modes && modes != (SDL_Rect **)-1) {
909 >                max_width = modes[0]->w;
910 >                max_height = modes[0]->h;
911 >                if (default_width > max_width)
912 >                        default_width = max_width;
913 >                if (default_height > max_height)
914 >                        default_height = max_height;
915          }
916          if (default_width <= 0)
917                  default_width = max_width;
# Line 665 | Line 920 | bool VideoInit(bool classic)
920  
921          // Mac screen depth follows X depth
922          screen_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
923 <        video_depth default_depth;
923 >        int default_depth;
924          switch (screen_depth) {
925          case 8:
926 <                default_depth = VDEPTH_8BIT;
926 >                default_depth = VIDEO_DEPTH_8BIT;
927                  break;
928          case 15: case 16:
929 <                default_depth = VDEPTH_16BIT;
929 >                default_depth = VIDEO_DEPTH_16BIT;
930                  break;
931          case 24: case 32:
932 <                default_depth = VDEPTH_32BIT;
932 >                default_depth = VIDEO_DEPTH_32BIT;
933                  break;
934          default:
935 <                default_depth =  VDEPTH_1BIT;
935 >                default_depth =  VIDEO_DEPTH_1BIT;
936                  break;
937          }
938  
939          // Construct list of supported modes
940          if (display_type == DISPLAY_WINDOW) {
941                  if (classic)
942 <                        add_mode(512, 342, 0x80, 64, VDEPTH_1BIT);
942 >                        add_mode(display_type, 512, 342, 0x80, 64, VIDEO_DEPTH_1BIT);
943                  else {
944 <                        for (int d = VDEPTH_1BIT; d <= default_depth; d++) {
945 <                                int bpp = (d <= VDEPTH_8BIT ? 8 : sdl_depth_of_video_depth(d));
944 >                        for (int d = VIDEO_DEPTH_1BIT; d <= default_depth; d++) {
945 >                                int bpp = (d <= VIDEO_DEPTH_8BIT ? 8 : sdl_depth_of_video_depth(d));
946                                  if (SDL_VideoModeOK(max_width, max_height, bpp, SDL_HWSURFACE))
947                                          add_window_modes(video_depth(d));
948                          }
949                  }
950          } else
951 <                add_mode(default_width, default_height, 0x80, TrivialBytesPerRow(default_width, default_depth), default_depth);
951 >                add_mode(display_type, default_width, default_height, 0x80, TrivialBytesPerRow(default_width, (video_depth)default_depth), default_depth);
952          if (VideoModes.empty()) {
953                  ErrorAlert(STR_NO_XVISUAL_ERR);
954                  return false;
# Line 701 | Line 956 | bool VideoInit(bool classic)
956  
957          // Find requested default mode with specified dimensions
958          uint32 default_id;
959 <        std::vector<video_mode>::const_iterator i, end = VideoModes.end();
959 >        std::vector<VIDEO_MODE>::const_iterator i, end = VideoModes.end();
960          for (i = VideoModes.begin(); i != end; ++i) {
961 <                if (i->x == default_width && i->y == default_height && i->depth == default_depth) {
962 <                        default_id = i->resolution_id;
961 >                const VIDEO_MODE & mode = (*i);
962 >                if (VIDEO_MODE_X == default_width && VIDEO_MODE_Y == default_height && VIDEO_MODE_DEPTH == default_depth) {
963 >                        default_id = VIDEO_MODE_RESOLUTION;
964 > #ifdef SHEEPSHAVER
965 >                        std::vector<VIDEO_MODE>::const_iterator begin = VideoModes.begin();
966 >                        cur_mode = distance(begin, i);
967 > #endif
968                          break;
969                  }
970          }
971          if (i == end) { // not found, use first available mode
972 <                default_depth = VideoModes[0].depth;
973 <                default_id = VideoModes[0].resolution_id;
972 >                const VIDEO_MODE & mode = VideoModes[0];
973 >                default_depth = VIDEO_MODE_DEPTH;
974 >                default_id = VIDEO_MODE_RESOLUTION;
975 > #ifdef SHEEPSHAVER
976 >                cur_mode = 0;
977 > #endif
978          }
979  
980 + #ifdef SHEEPSHAVER
981 +        for (int i = 0; i < VideoModes.size(); i++)
982 +                VModes[i] = VideoModes[i];
983 +        VideoInfo *p = &VModes[VideoModes.size()];
984 +        p->viType = DIS_INVALID;        // End marker
985 +        p->viRowBytes = 0;
986 +        p->viXsize = p->viYsize = 0;
987 +        p->viAppleMode = 0;
988 +        p->viAppleID = 0;
989 + #endif
990 +
991   #if DEBUG
992          D(bug("Available video modes:\n"));
993          for (i = VideoModes.begin(); i != end; ++i) {
994 <                int bits = 1 << i->depth;
994 >                const VIDEO_MODE & mode = (*i);
995 >                int bits = 1 << VIDEO_MODE_DEPTH;
996                  if (bits == 16)
997                          bits = 15;
998                  else if (bits == 32)
999                          bits = 24;
1000 <                D(bug(" %dx%d (ID %02x), %d colors\n", i->x, i->y, i->resolution_id, 1 << bits));
1000 >                D(bug(" %dx%d (ID %02x), %d colors\n", VIDEO_MODE_X, VIDEO_MODE_Y, VIDEO_MODE_RESOLUTION, 1 << bits));
1001          }
1002   #endif
1003  
1004          // Create SDL_monitor_desc for this (the only) display
1005 <        SDL_monitor_desc *monitor = new SDL_monitor_desc(VideoModes, default_depth, default_id);
1005 >        SDL_monitor_desc *monitor = new SDL_monitor_desc(VideoModes, (video_depth)default_depth, default_id);
1006          VideoMonitors.push_back(monitor);
1007  
1008          // Open display
# Line 746 | Line 1022 | void SDL_monitor_desc::video_close(void)
1022          // Stop redraw thread
1023          if (redraw_thread_active) {
1024                  redraw_thread_cancel = true;
1025 < //              SDL_WaitThread(redraw_thread, NULL); doesn't work
750 <                while (redraw_thread_cancel);
1025 >                SDL_WaitThread(redraw_thread, NULL);
1026          }
1027          redraw_thread_active = false;
1028  
# Line 797 | Line 1072 | void VideoQuitFullScreen(void)
1072   *  Mac VBL interrupt
1073   */
1074  
1075 + /*
1076 + *  Execute video VBL routine
1077 + */
1078 +
1079 + #ifdef SHEEPSHAVER
1080 + void VideoVBL(void)
1081 + {
1082 +        // Emergency quit requested? Then quit
1083 +        if (emerg_quit)
1084 +                QuitEmulator();
1085 +
1086 +        // Temporarily give up frame buffer lock (this is the point where
1087 +        // we are suspended when the user presses Ctrl-Tab)
1088 +        UNLOCK_FRAME_BUFFER;
1089 +        LOCK_FRAME_BUFFER;
1090 +
1091 +        // Execute video VBL
1092 +        if (private_data != NULL && private_data->interruptsEnabled)
1093 +                VSLDoInterruptService(private_data->vslServiceID);
1094 + }
1095 + #else
1096   void VideoInterrupt(void)
1097   {
1098 +        // We must fill in the events queue in the same thread that did call SDL_SetVideoMode()
1099 +        SDL_PumpEvents();
1100 +
1101          // Emergency quit requested? Then quit
1102          if (emerg_quit)
1103                  QuitEmulator();
# Line 808 | Line 1107 | void VideoInterrupt(void)
1107          UNLOCK_FRAME_BUFFER;
1108          LOCK_FRAME_BUFFER;
1109   }
1110 + #endif
1111  
1112  
1113   /*
1114   *  Set palette
1115   */
1116  
1117 + #ifdef SHEEPSHAVER
1118 + void video_set_palette(void)
1119 + {
1120 +        monitor_desc * monitor = VideoMonitors[0];
1121 +        int n_colors = palette_size(monitor->get_current_mode().viAppleMode);
1122 +        uint8 pal[256 * 3];
1123 +        for (int c = 0; c < n_colors; c++) {
1124 +                pal[c*3 + 0] = mac_pal[c].red;
1125 +                pal[c*3 + 1] = mac_pal[c].green;
1126 +                pal[c*3 + 2] = mac_pal[c].blue;
1127 +        }
1128 +        monitor->set_palette(pal, n_colors);
1129 + }
1130 + #endif
1131 +
1132   void SDL_monitor_desc::set_palette(uint8 *pal, int num_in)
1133   {
1134 <        const video_mode &mode = get_current_mode();
1134 >        const VIDEO_MODE &mode = get_current_mode();
1135  
1136          // FIXME: how can we handle the gamma ramp?
1137 <        if (mode.depth > VDEPTH_8BIT)
1137 >        if (VIDEO_MODE_DEPTH > VIDEO_DEPTH_8BIT)
1138                  return;
1139  
1140          LOCK_PALETTE;
# Line 848 | Line 1163 | void SDL_monitor_desc::set_palette(uint8
1163                  LOCK_VOSF;
1164                  PFLAG_SET_ALL;
1165                  UNLOCK_VOSF;
1166 <                memset(the_buffer_copy, 0, mode.bytes_per_row * mode.y);
1166 >                memset(the_buffer_copy, 0, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y);
1167   #endif
1168          }
1169  
# Line 863 | Line 1178 | void SDL_monitor_desc::set_palette(uint8
1178   *  Switch video mode
1179   */
1180  
1181 + #ifdef SHEEPSHAVER
1182 + int16 video_mode_change(VidLocals *csSave, uint32 ParamPtr)
1183 + {
1184 +        /* return if no mode change */
1185 +        if ((csSave->saveData == ReadMacInt32(ParamPtr + csData)) &&
1186 +            (csSave->saveMode == ReadMacInt16(ParamPtr + csMode))) return noErr;
1187 +
1188 +        /* first find video mode in table */
1189 +        for (int i=0; VModes[i].viType != DIS_INVALID; i++) {
1190 +                if ((ReadMacInt16(ParamPtr + csMode) == VModes[i].viAppleMode) &&
1191 +                    (ReadMacInt32(ParamPtr + csData) == VModes[i].viAppleID)) {
1192 +                        csSave->saveMode = ReadMacInt16(ParamPtr + csMode);
1193 +                        csSave->saveData = ReadMacInt32(ParamPtr + csData);
1194 +                        csSave->savePage = ReadMacInt16(ParamPtr + csPage);
1195 +
1196 +                        // Disable interrupts
1197 +                        DisableInterrupt();
1198 +
1199 +                        cur_mode = i;
1200 +                        monitor_desc *monitor = VideoMonitors[0];
1201 +                        monitor->switch_to_current_mode();
1202 +
1203 +                        WriteMacInt32(ParamPtr + csBaseAddr, screen_base);
1204 +                        csSave->saveBaseAddr=screen_base;
1205 +                        csSave->saveData=VModes[cur_mode].viAppleID;/* First mode ... */
1206 +                        csSave->saveMode=VModes[cur_mode].viAppleMode;
1207 +
1208 +                        // Enable interrupts
1209 +                        EnableInterrupt();
1210 +                        return noErr;
1211 +                }
1212 +        }
1213 +        return paramErr;
1214 + }
1215 + #endif
1216 +
1217   void SDL_monitor_desc::switch_to_current_mode(void)
1218   {
1219          // Close and reopen display
# Line 877 | Line 1228 | void SDL_monitor_desc::switch_to_current
1228  
1229  
1230   /*
1231 + *  Can we set the MacOS cursor image into the window?
1232 + */
1233 +
1234 + #ifdef SHEEPSHAVER
1235 + bool video_can_change_cursor(void)
1236 + {
1237 +        return (display_type == DISPLAY_WINDOW);
1238 + }
1239 + #endif
1240 +
1241 +
1242 + /*
1243 + *  Set cursor image for window
1244 + */
1245 +
1246 + #ifdef SHEEPSHAVER
1247 + void video_set_cursor(void)
1248 + {
1249 +        cursor_changed = true;
1250 + }
1251 + #endif
1252 +
1253 +
1254 + /*
1255 + *  Install graphics acceleration
1256 + */
1257 +
1258 + #ifdef SHEEPSHAVER
1259 + // Rectangle inversion
1260 + template< int bpp >
1261 + static inline void do_invrect(uint8 *dest, uint32 length)
1262 + {
1263 + #define INVERT_1(PTR, OFS) ((uint8  *)(PTR))[OFS] = ~((uint8  *)(PTR))[OFS]
1264 + #define INVERT_2(PTR, OFS) ((uint16 *)(PTR))[OFS] = ~((uint16 *)(PTR))[OFS]
1265 + #define INVERT_4(PTR, OFS) ((uint32 *)(PTR))[OFS] = ~((uint32 *)(PTR))[OFS]
1266 + #define INVERT_8(PTR, OFS) ((uint64 *)(PTR))[OFS] = ~((uint64 *)(PTR))[OFS]
1267 +
1268 + #ifndef UNALIGNED_PROFITABLE
1269 +        // Align on 16-bit boundaries
1270 +        if (bpp < 16 && (((uintptr)dest) & 1)) {
1271 +                INVERT_1(dest, 0);
1272 +                dest += 1; length -= 1;
1273 +        }
1274 +
1275 +        // Align on 32-bit boundaries
1276 +        if (bpp < 32 && (((uintptr)dest) & 2)) {
1277 +                INVERT_2(dest, 0);
1278 +                dest += 2; length -= 2;
1279 +        }
1280 + #endif
1281 +
1282 +        // Invert 8-byte words
1283 +        if (length >= 8) {
1284 +                const int r = (length / 8) % 8;
1285 +                dest += r * 8;
1286 +
1287 +                int n = ((length / 8) + 7) / 8;
1288 +                switch (r) {
1289 +                case 0: do {
1290 +                                dest += 64;
1291 +                                INVERT_8(dest, -8);
1292 +                case 7: INVERT_8(dest, -7);
1293 +                case 6: INVERT_8(dest, -6);
1294 +                case 5: INVERT_8(dest, -5);
1295 +                case 4: INVERT_8(dest, -4);
1296 +                case 3: INVERT_8(dest, -3);
1297 +                case 2: INVERT_8(dest, -2);
1298 +                case 1: INVERT_8(dest, -1);
1299 +                                } while (--n > 0);
1300 +                }
1301 +        }
1302 +
1303 +        // 32-bit cell to invert?
1304 +        if (length & 4) {
1305 +                INVERT_4(dest, 0);
1306 +                if (bpp <= 16)
1307 +                        dest += 4;
1308 +        }
1309 +
1310 +        // 16-bit cell to invert?
1311 +        if (bpp <= 16 && (length & 2)) {
1312 +                INVERT_2(dest, 0);
1313 +                if (bpp <= 8)
1314 +                        dest += 2;
1315 +        }
1316 +
1317 +        // 8-bit cell to invert?
1318 +        if (bpp <= 8 && (length & 1))
1319 +                INVERT_1(dest, 0);
1320 +
1321 + #undef INVERT_1
1322 + #undef INVERT_2
1323 + #undef INVERT_4
1324 + #undef INVERT_8
1325 + }
1326 +
1327 + void NQD_invrect(uint32 p)
1328 + {
1329 +        D(bug("accl_invrect %08x\n", p));
1330 +
1331 +        // Get inversion parameters
1332 +        int16 dest_X = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2);
1333 +        int16 dest_Y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0);
1334 +        int16 width  = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2);
1335 +        int16 height = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0);
1336 +        D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y));
1337 +        D(bug(" width %d, height %d, bytes_per_row %d\n", width, height, (int32)ReadMacInt32(p + acclDestRowBytes)));
1338 +
1339 +        //!!?? pen_mode == 14
1340 +
1341 +        // And perform the inversion
1342 +        const int bpp = bytes_per_pixel(ReadMacInt32(p + acclDestPixelSize));
1343 +        const int dest_row_bytes = (int32)ReadMacInt32(p + acclDestRowBytes);
1344 +        uint8 *dest = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + (dest_Y * dest_row_bytes) + (dest_X * bpp));
1345 +        width *= bpp;
1346 +        switch (bpp) {
1347 +        case 1:
1348 +                for (int i = 0; i < height; i++) {
1349 +                        do_invrect<8>(dest, width);
1350 +                        dest += dest_row_bytes;
1351 +                }
1352 +                break;
1353 +        case 2:
1354 +                for (int i = 0; i < height; i++) {
1355 +                        do_invrect<16>(dest, width);
1356 +                        dest += dest_row_bytes;
1357 +                }
1358 +                break;
1359 +        case 4:
1360 +                for (int i = 0; i < height; i++) {
1361 +                        do_invrect<32>(dest, width);
1362 +                        dest += dest_row_bytes;
1363 +                }
1364 +                break;
1365 +        }
1366 + }
1367 +
1368 + // Rectangle filling
1369 + template< int bpp >
1370 + static inline void do_fillrect(uint8 *dest, uint32 color, uint32 length)
1371 + {
1372 + #define FILL_1(PTR, OFS, VAL) ((uint8  *)(PTR))[OFS] = (VAL)
1373 + #define FILL_2(PTR, OFS, VAL) ((uint16 *)(PTR))[OFS] = (VAL)
1374 + #define FILL_4(PTR, OFS, VAL) ((uint32 *)(PTR))[OFS] = (VAL)
1375 + #define FILL_8(PTR, OFS, VAL) ((uint64 *)(PTR))[OFS] = (VAL)
1376 +
1377 + #ifndef UNALIGNED_PROFITABLE
1378 +        // Align on 16-bit boundaries
1379 +        if (bpp < 16 && (((uintptr)dest) & 1)) {
1380 +                FILL_1(dest, 0, color);
1381 +                dest += 1; length -= 1;
1382 +        }
1383 +
1384 +        // Align on 32-bit boundaries
1385 +        if (bpp < 32 && (((uintptr)dest) & 2)) {
1386 +                FILL_2(dest, 0, color);
1387 +                dest += 2; length -= 2;
1388 +        }
1389 + #endif
1390 +
1391 +        // Fill 8-byte words
1392 +        if (length >= 8) {
1393 +                const uint64 c = (((uint64)color) << 32) | color;
1394 +                const int r = (length / 8) % 8;
1395 +                dest += r * 8;
1396 +
1397 +                int n = ((length / 8) + 7) / 8;
1398 +                switch (r) {
1399 +                case 0: do {
1400 +                                dest += 64;
1401 +                                FILL_8(dest, -8, c);
1402 +                case 7: FILL_8(dest, -7, c);
1403 +                case 6: FILL_8(dest, -6, c);
1404 +                case 5: FILL_8(dest, -5, c);
1405 +                case 4: FILL_8(dest, -4, c);
1406 +                case 3: FILL_8(dest, -3, c);
1407 +                case 2: FILL_8(dest, -2, c);
1408 +                case 1: FILL_8(dest, -1, c);
1409 +                                } while (--n > 0);
1410 +                }
1411 +        }
1412 +
1413 +        // 32-bit cell to fill?
1414 +        if (length & 4) {
1415 +                FILL_4(dest, 0, color);
1416 +                if (bpp <= 16)
1417 +                        dest += 4;
1418 +        }
1419 +
1420 +        // 16-bit cell to fill?
1421 +        if (bpp <= 16 && (length & 2)) {
1422 +                FILL_2(dest, 0, color);
1423 +                if (bpp <= 8)
1424 +                        dest += 2;
1425 +        }
1426 +
1427 +        // 8-bit cell to fill?
1428 +        if (bpp <= 8 && (length & 1))
1429 +                FILL_1(dest, 0, color);
1430 +
1431 + #undef FILL_1
1432 + #undef FILL_2
1433 + #undef FILL_4
1434 + #undef FILL_8
1435 + }
1436 +
1437 + void NQD_fillrect(uint32 p)
1438 + {
1439 +        D(bug("accl_fillrect %08x\n", p));
1440 +
1441 +        // Get filling parameters
1442 +        int16 dest_X = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2);
1443 +        int16 dest_Y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0);
1444 +        int16 width  = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2);
1445 +        int16 height = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0);
1446 +        uint32 color = htonl(ReadMacInt32(p + acclPenMode) == 8 ? ReadMacInt32(p + acclForePen) : ReadMacInt32(p + acclBackPen));
1447 +        D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y));
1448 +        D(bug(" width %d, height %d\n", width, height));
1449 +        D(bug(" bytes_per_row %d color %08x\n", (int32)ReadMacInt32(p + acclDestRowBytes), color));
1450 +
1451 +        // And perform the fill
1452 +        const int bpp = bytes_per_pixel(ReadMacInt32(p + acclDestPixelSize));
1453 +        const int dest_row_bytes = (int32)ReadMacInt32(p + acclDestRowBytes);
1454 +        uint8 *dest = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + (dest_Y * dest_row_bytes) + (dest_X * bpp));
1455 +        width *= bpp;
1456 +        switch (bpp) {
1457 +        case 1:
1458 +                for (int i = 0; i < height; i++) {
1459 +                        memset(dest, color, width);
1460 +                        dest += dest_row_bytes;
1461 +                }
1462 +                break;
1463 +        case 2:
1464 +                for (int i = 0; i < height; i++) {
1465 +                        do_fillrect<16>(dest, color, width);
1466 +                        dest += dest_row_bytes;
1467 +                }
1468 +                break;
1469 +        case 4:
1470 +                for (int i = 0; i < height; i++) {
1471 +                        do_fillrect<32>(dest, color, width);
1472 +                        dest += dest_row_bytes;
1473 +                }
1474 +                break;
1475 +        }
1476 + }
1477 +
1478 + bool NQD_fillrect_hook(uint32 p)
1479 + {
1480 +        D(bug("accl_fillrect_hook %08x\n", p));
1481 +
1482 +        // Check if we can accelerate this fillrect
1483 +        if (ReadMacInt32(p + 0x284) != 0 && ReadMacInt32(p + acclDestPixelSize) >= 8) {
1484 +                const int transfer_mode = ReadMacInt32(p + acclTransferMode);
1485 +                if (transfer_mode == 8) {
1486 +                        // Fill
1487 +                        WriteMacInt32(p + acclDrawProc, NativeTVECT(NATIVE_FILLRECT));
1488 +                        return true;
1489 +                }
1490 +                else if (transfer_mode == 10) {
1491 +                        // Invert
1492 +                        WriteMacInt32(p + acclDrawProc, NativeTVECT(NATIVE_INVRECT));
1493 +                        return true;
1494 +                }
1495 +        }
1496 +        return false;
1497 + }
1498 +
1499 + // Rectangle blitting
1500 + // TODO: optimize for VOSF and target pixmap == screen
1501 + void NQD_bitblt(uint32 p)
1502 + {
1503 +        D(bug("accl_bitblt %08x\n", p));
1504 +
1505 +        // Get blitting parameters
1506 +        int16 src_X  = (int16)ReadMacInt16(p + acclSrcRect + 2) - (int16)ReadMacInt16(p + acclSrcBoundsRect + 2);
1507 +        int16 src_Y  = (int16)ReadMacInt16(p + acclSrcRect + 0) - (int16)ReadMacInt16(p + acclSrcBoundsRect + 0);
1508 +        int16 dest_X = (int16)ReadMacInt16(p + acclDestRect + 2) - (int16)ReadMacInt16(p + acclDestBoundsRect + 2);
1509 +        int16 dest_Y = (int16)ReadMacInt16(p + acclDestRect + 0) - (int16)ReadMacInt16(p + acclDestBoundsRect + 0);
1510 +        int16 width  = (int16)ReadMacInt16(p + acclDestRect + 6) - (int16)ReadMacInt16(p + acclDestRect + 2);
1511 +        int16 height = (int16)ReadMacInt16(p + acclDestRect + 4) - (int16)ReadMacInt16(p + acclDestRect + 0);
1512 +        D(bug(" src addr %08x, dest addr %08x\n", ReadMacInt32(p + acclSrcBaseAddr), ReadMacInt32(p + acclDestBaseAddr)));
1513 +        D(bug(" src X %d, src Y %d, dest X %d, dest Y %d\n", src_X, src_Y, dest_X, dest_Y));
1514 +        D(bug(" width %d, height %d\n", width, height));
1515 +
1516 +        // And perform the blit
1517 +        const int bpp = bytes_per_pixel(ReadMacInt32(p + acclSrcPixelSize));
1518 +        width *= bpp;
1519 +        if ((int32)ReadMacInt32(p + acclSrcRowBytes) > 0) {
1520 +                const int src_row_bytes = (int32)ReadMacInt32(p + acclSrcRowBytes);
1521 +                const int dst_row_bytes = (int32)ReadMacInt32(p + acclDestRowBytes);
1522 +                uint8 *src = Mac2HostAddr(ReadMacInt32(p + acclSrcBaseAddr) + (src_Y * src_row_bytes) + (src_X * bpp));
1523 +                uint8 *dst = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + (dest_Y * dst_row_bytes) + (dest_X * bpp));
1524 +                for (int i = 0; i < height; i++) {
1525 +                        memmove(dst, src, width);
1526 +                        src += src_row_bytes;
1527 +                        dst += dst_row_bytes;
1528 +                }
1529 +        }
1530 +        else {
1531 +                const int src_row_bytes = -(int32)ReadMacInt32(p + acclSrcRowBytes);
1532 +                const int dst_row_bytes = -(int32)ReadMacInt32(p + acclDestRowBytes);
1533 +                uint8 *src = Mac2HostAddr(ReadMacInt32(p + acclSrcBaseAddr) + ((src_Y + height - 1) * src_row_bytes) + (src_X * bpp));
1534 +                uint8 *dst = Mac2HostAddr(ReadMacInt32(p + acclDestBaseAddr) + ((dest_Y + height - 1) * dst_row_bytes) + (dest_X * bpp));
1535 +                for (int i = height - 1; i >= 0; i--) {
1536 +                        memmove(dst, src, width);
1537 +                        src -= src_row_bytes;
1538 +                        dst -= dst_row_bytes;
1539 +                }
1540 +        }
1541 + }
1542 +
1543 + /*
1544 +  BitBlt transfer modes:
1545 +  0 : srcCopy
1546 +  1 : srcOr
1547 +  2 : srcXor
1548 +  3 : srcBic
1549 +  4 : notSrcCopy
1550 +  5 : notSrcOr
1551 +  6 : notSrcXor
1552 +  7 : notSrcBic
1553 +  32 : blend
1554 +  33 : addPin
1555 +  34 : addOver
1556 +  35 : subPin
1557 +  36 : transparent
1558 +  37 : adMax
1559 +  38 : subOver
1560 +  39 : adMin
1561 +  50 : hilite
1562 + */
1563 +
1564 + bool NQD_bitblt_hook(uint32 p)
1565 + {
1566 +        D(bug("accl_draw_hook %08x\n", p));
1567 +
1568 +        // Check if we can accelerate this bitblt
1569 +        if (ReadMacInt32(p + 0x018) + ReadMacInt32(p + 0x128) == 0 &&
1570 +                ReadMacInt32(p + 0x130) == 0 &&
1571 +                ReadMacInt32(p + acclSrcPixelSize) >= 8 &&
1572 +                ReadMacInt32(p + acclSrcPixelSize) == ReadMacInt32(p + acclDestPixelSize) &&
1573 +                (ReadMacInt32(p + acclSrcRowBytes) ^ ReadMacInt32(p + acclDestRowBytes)) >= 0 && // same sign?
1574 +                ReadMacInt32(p + acclTransferMode) == 0 &&                                                                               // srcCopy?
1575 +                ReadMacInt32(p + 0x15c) > 0) {
1576 +
1577 +                // Yes, set function pointer
1578 +                WriteMacInt32(p + acclDrawProc, NativeTVECT(NATIVE_BITBLT));
1579 +                return true;
1580 +        }
1581 +        return false;
1582 + }
1583 +
1584 + // Wait for graphics operation to finish
1585 + bool NQD_sync_hook(uint32 arg)
1586 + {
1587 +        D(bug("accl_sync_hook %08x\n", arg));
1588 +        return true;
1589 + }
1590 +
1591 + void VideoInstallAccel(void)
1592 + {
1593 +        // Install acceleration hooks
1594 +        if (PrefsFindBool("gfxaccel")) {
1595 +                D(bug("Video: Installing acceleration hooks\n"));
1596 +                uint32 base;
1597 +
1598 +                SheepVar bitblt_hook_info(sizeof(accl_hook_info));
1599 +                base = bitblt_hook_info.addr();
1600 +                WriteMacInt32(base + 0, NativeTVECT(NATIVE_BITBLT_HOOK));
1601 +                WriteMacInt32(base + 4, NativeTVECT(NATIVE_SYNC_HOOK));
1602 +                WriteMacInt32(base + 8, ACCL_BITBLT);
1603 +                NQDMisc(6, bitblt_hook_info.ptr());
1604 +
1605 +                SheepVar fillrect_hook_info(sizeof(accl_hook_info));
1606 +                base = fillrect_hook_info.addr();
1607 +                WriteMacInt32(base + 0, NativeTVECT(NATIVE_FILLRECT_HOOK));
1608 +                WriteMacInt32(base + 4, NativeTVECT(NATIVE_SYNC_HOOK));
1609 +                WriteMacInt32(base + 8, ACCL_FILLRECT);
1610 +                NQDMisc(6, fillrect_hook_info.ptr());
1611 +        }
1612 + }
1613 + #endif
1614 +
1615 +
1616 + /*
1617   *  Translate key event to Mac keycode, returns -1 if no keycode was found
1618   *  and -2 if the key was recognized as a hotkey
1619   */
# Line 1021 | Line 1758 | static int event2keycode(SDL_KeyboardEve
1758  
1759   static void handle_events(void)
1760   {
1761 <        SDL_Event event;
1762 <        while (SDL_PollEvent(&event)) {
1763 <                switch (event.type) {
1761 >        SDL_Event events[10];
1762 >        const int n_max_events = sizeof(events) / sizeof(events[0]);
1763 >        int n_events;
1764 >
1765 >        while ((n_events = SDL_PeepEvents(events, n_max_events, SDL_GETEVENT, sdl_eventmask)) > 0) {
1766 >                for (int i = 0; i < n_events; i++) {
1767 >                        SDL_Event const & event = events[i];
1768 >                        switch (event.type) {
1769  
1770                          // Mouse button
1771                          case SDL_MOUSEBUTTONDOWN: {
# Line 1104 | Line 1846 | static void handle_events(void)
1846                          // Hidden parts exposed, force complete refresh of window
1847                          case SDL_VIDEOEXPOSE:
1848                                  if (display_type == DISPLAY_WINDOW) {
1849 <                                        const video_mode &mode = VideoMonitors[0]->get_current_mode();
1849 >                                        const VIDEO_MODE &mode = VideoMonitors[0]->get_current_mode();
1850   #ifdef ENABLE_VOSF
1851                                          if (use_vosf) {                 // VOSF refresh
1852                                                  LOCK_VOSF;
1853                                                  PFLAG_SET_ALL;
1854                                                  UNLOCK_VOSF;
1855 <                                                memset(the_buffer_copy, 0, mode.bytes_per_row * mode.y);
1855 >                                                memset(the_buffer_copy, 0, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y);
1856                                          }
1857                                          else
1858   #endif
1859 <                                                memset(the_buffer_copy, 0, mode.bytes_per_row * mode.y);
1859 >                                                memset(the_buffer_copy, 0, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y);
1860                                  }
1861                                  break;
1862  
# Line 1123 | Line 1865 | static void handle_events(void)
1865                                  ADBKeyDown(0x7f);       // Power key
1866                                  ADBKeyUp(0x7f);
1867                                  break;
1868 +                        }
1869                  }
1870          }
1871   }
# Line 1137 | Line 1880 | static void update_display_static(driver
1880   {
1881          // Incremental update code
1882          int wide = 0, high = 0, x1, x2, y1, y2, i, j;
1883 <        const video_mode &mode = drv->mode;
1884 <        int bytes_per_row = mode.bytes_per_row;
1883 >        const VIDEO_MODE &mode = drv->mode;
1884 >        int bytes_per_row = VIDEO_MODE_ROW_BYTES;
1885          uint8 *p, *p2;
1886  
1887          // Check for first line from top and first line from bottom that have changed
1888          y1 = 0;
1889 <        for (j=0; j<mode.y; j++) {
1889 >        for (j=0; j<VIDEO_MODE_Y; j++) {
1890                  if (memcmp(&the_buffer[j * bytes_per_row], &the_buffer_copy[j * bytes_per_row], bytes_per_row)) {
1891                          y1 = j;
1892                          break;
1893                  }
1894          }
1895          y2 = y1 - 1;
1896 <        for (j=mode.y-1; j>=y1; j--) {
1896 >        for (j=VIDEO_MODE_Y-1; j>=y1; j--) {
1897                  if (memcmp(&the_buffer[j * bytes_per_row], &the_buffer_copy[j * bytes_per_row], bytes_per_row)) {
1898                          y2 = j;
1899                          break;
# Line 1160 | Line 1903 | static void update_display_static(driver
1903  
1904          // Check for first column from left and first column from right that have changed
1905          if (high) {
1906 <                if (mode.depth < VDEPTH_8BIT) {
1906 >                if (VIDEO_MODE_DEPTH < VIDEO_DEPTH_8BIT) {
1907                          const int src_bytes_per_row = bytes_per_row;
1908                          const int dst_bytes_per_row = drv->s->pitch;
1909 <                        const int pixels_per_byte = mode.x / src_bytes_per_row;
1909 >                        const int pixels_per_byte = VIDEO_MODE_X / src_bytes_per_row;
1910  
1911 <                        x1 = mode.x / pixels_per_byte;
1911 >                        x1 = VIDEO_MODE_X / pixels_per_byte;
1912                          for (j = y1; j <= y2; j++) {
1913                                  p = &the_buffer[j * bytes_per_row];
1914                                  p2 = &the_buffer_copy[j * bytes_per_row];
# Line 1183 | Line 1926 | static void update_display_static(driver
1926                                  p2 = &the_buffer_copy[j * bytes_per_row];
1927                                  p += bytes_per_row;
1928                                  p2 += bytes_per_row;
1929 <                                for (i = (mode.x / pixels_per_byte); i > x2; i--) {
1929 >                                for (i = (VIDEO_MODE_X / pixels_per_byte); i > x2; i--) {
1930                                          p--; p2--;
1931                                          if (*p != *p2) {
1932                                                  x2 = i;
# Line 1221 | Line 1964 | static void update_display_static(driver
1964                          }
1965  
1966                  } else {
1967 <                        const int bytes_per_pixel = mode.bytes_per_row / mode.x;
1967 >                        const int bytes_per_pixel = VIDEO_MODE_ROW_BYTES / VIDEO_MODE_X;
1968  
1969 <                        x1 = mode.x;
1969 >                        x1 = VIDEO_MODE_X;
1970                          for (j=y1; j<=y2; j++) {
1971                                  p = &the_buffer[j * bytes_per_row];
1972                                  p2 = &the_buffer_copy[j * bytes_per_row];
# Line 1241 | Line 1984 | static void update_display_static(driver
1984                                  p2 = &the_buffer_copy[j * bytes_per_row];
1985                                  p += bytes_per_row;
1986                                  p2 += bytes_per_row;
1987 <                                for (i=mode.x*bytes_per_pixel; i>x2*bytes_per_pixel; i--) {
1987 >                                for (i=VIDEO_MODE_X*bytes_per_pixel; i>x2*bytes_per_pixel; i--) {
1988                                          p--;
1989                                          p2--;
1990                                          if (*p != *p2) {
# Line 1401 | Line 2144 | static void VideoRefreshInit(void)
2144          }
2145   }
2146  
2147 + const int VIDEO_REFRESH_HZ = 60;
2148 + const int VIDEO_REFRESH_DELAY = 1000000 / VIDEO_REFRESH_HZ;
2149 +
2150   static int redraw_func(void *arg)
2151   {
2152          uint64 start = GetTicks_usec();
2153          int64 ticks = 0;
2154 +        uint64 next = GetTicks_usec() + VIDEO_REFRESH_DELAY;
2155  
2156          while (!redraw_thread_cancel) {
2157  
2158                  // Wait
2159 <                Delay_usec(16667);
2159 >                next += VIDEO_REFRESH_DELAY;
2160 >                int64 delay = next - GetTicks_usec();
2161 >                if (delay > 0)
2162 >                        Delay_usec(delay);
2163 >                else if (delay < -VIDEO_REFRESH_DELAY)
2164 >                        next = GetTicks_usec();
2165 >                ticks++;
2166  
2167                  // Handle SDL events
2168                  handle_events();
2169  
2170                  // Refresh display
2171                  video_refresh();
2172 <                ticks++;
2172 >
2173 > #ifdef SHEEPSHAVER
2174 >                // Set new cursor image if it was changed
2175 >                if (cursor_changed && sdl_cursor) {
2176 >                        cursor_changed = false;
2177 >                        SDL_FreeCursor(sdl_cursor);
2178 >                        sdl_cursor = SDL_CreateCursor(MacCursor + 4, MacCursor + 36, 16, 16, MacCursor[2], MacCursor[3]);
2179 >                        if (sdl_cursor)
2180 >                                SDL_SetCursor(sdl_cursor);
2181 >                }
2182 > #endif
2183  
2184                  // Set new palette if it was changed
2185                  handle_palette_changes();
# Line 1424 | Line 2187 | static int redraw_func(void *arg)
2187  
2188          uint64 end = GetTicks_usec();
2189          D(bug("%lld refreshes in %lld usec = %f refreshes/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
1427        redraw_thread_cancel = false;
2190          return 0;
2191   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines