From 8871da753dec7ae288ec3223f9f80f7d0f4beb8d Mon Sep 17 00:00:00 2001 From: cebix <> Date: Thu, 25 Apr 2002 11:00:31 +0000 Subject: [PATCH] - added infrastructure for multi-monitor support; only video_x.cpp is converted for the new scheme; not actually tested with a mult-monitor setup yet but at least single-monitor display doesn't seem to be broken (UAE banked addressing would definitely require some extensions to handle multiple frame buffers) - struct video_mode has an extra field that is free for use by platform- specific code --- BasiliskII/src/Unix/video_vosf.h | 46 ++- BasiliskII/src/Unix/video_x.cpp | 248 +++++++------ BasiliskII/src/include/video.h | 161 ++++++-- BasiliskII/src/main.cpp | 3 +- BasiliskII/src/slot_rom.cpp | 115 +++--- BasiliskII/src/video.cpp | 608 ++++++++++++++++--------------- 6 files changed, 676 insertions(+), 505 deletions(-) diff --git a/BasiliskII/src/Unix/video_vosf.h b/BasiliskII/src/Unix/video_vosf.h index ebec5340..df866ba0 100644 --- a/BasiliskII/src/Unix/video_vosf.h +++ b/BasiliskII/src/Unix/video_vosf.h @@ -163,8 +163,10 @@ static uint32 page_extend(uint32 size) static bool screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction); -static bool video_vosf_init(void) +static bool video_vosf_init(X11_monitor_desc &monitor) { + const video_mode &mode = monitor.get_current_mode(); + const uintptr page_size = getpagesize(); const uintptr page_mask = page_size - 1; @@ -196,13 +198,13 @@ static bool video_vosf_init(void) uint32 a = 0; for (unsigned i = 0; i < mainBuffer.pageCount; i++) { - unsigned y1 = a / VideoMonitor.mode.bytes_per_row; - if (y1 >= VideoMonitor.mode.y) - y1 = VideoMonitor.mode.y - 1; + unsigned y1 = a / mode.bytes_per_row; + if (y1 >= mode.y) + y1 = mode.y - 1; - unsigned y2 = (a + mainBuffer.pageSize) / VideoMonitor.mode.bytes_per_row; - if (y2 >= VideoMonitor.mode.y) - y2 = VideoMonitor.mode.y - 1; + unsigned y2 = (a + mainBuffer.pageSize) / mode.bytes_per_row; + if (y2 >= mode.y) + y2 = mode.y - 1; mainBuffer.pageInfo[i].top = y1; mainBuffer.pageInfo[i].bottom = y2; @@ -330,6 +332,8 @@ There are two cases to check: static inline void update_display_window_vosf(driver_window *drv) { + const video_mode &mode = drv->monitor.get_current_mode(); + int page = 0; for (;;) { const unsigned first_page = find_next_page_set(page); @@ -349,15 +353,15 @@ static inline void update_display_window_vosf(driver_window *drv) const int y2 = mainBuffer.pageInfo[page - 1].bottom; const int height = y2 - y1 + 1; - if (VideoMonitor.mode.depth < VDEPTH_8BIT) { + if (mode.depth < VDEPTH_8BIT) { // Update the_host_buffer and copy of the_buffer - const int src_bytes_per_row = VideoMonitor.mode.bytes_per_row; + const int src_bytes_per_row = mode.bytes_per_row; const int dst_bytes_per_row = drv->img->bytes_per_line; - const int pixels_per_byte = VideoMonitor.mode.x / src_bytes_per_row; + const int pixels_per_byte = mode.x / src_bytes_per_row; int i1 = y1 * src_bytes_per_row, i2 = y1 * dst_bytes_per_row, j; for (j = y1; j <= y2; j++) { - Screen_blit(the_host_buffer + i2, the_buffer + i1, VideoMonitor.mode.x / pixels_per_byte); + Screen_blit(the_host_buffer + i2, the_buffer + i1, mode.x / pixels_per_byte); i1 += src_bytes_per_row; i2 += dst_bytes_per_row; } @@ -365,21 +369,21 @@ static inline void update_display_window_vosf(driver_window *drv) } else { // Update the_host_buffer and copy of the_buffer - const int src_bytes_per_row = VideoMonitor.mode.bytes_per_row; + const int src_bytes_per_row = mode.bytes_per_row; const int dst_bytes_per_row = drv->img->bytes_per_line; - const int bytes_per_pixel = src_bytes_per_row / VideoMonitor.mode.x; + const int bytes_per_pixel = src_bytes_per_row / mode.x; int i1 = y1 * src_bytes_per_row, i2 = y1 * dst_bytes_per_row, j; for (j = y1; j <= y2; j++) { - Screen_blit(the_host_buffer + i2, the_buffer + i1, bytes_per_pixel * VideoMonitor.mode.x); + Screen_blit(the_host_buffer + i2, the_buffer + i1, bytes_per_pixel * mode.x); i1 += src_bytes_per_row; i2 += dst_bytes_per_row; } } if (drv->have_shm) - XShmPutImage(x_display, drv->w, drv->gc, drv->img, 0, y1, 0, y1, VideoMonitor.mode.x, height, 0); + XShmPutImage(x_display, drv->w, drv->gc, drv->img, 0, y1, 0, y1, mode.x, height, 0); else - XPutImage(x_display, drv->w, drv->gc, drv->img, 0, y1, 0, y1, VideoMonitor.mode.x, height); + XPutImage(x_display, drv->w, drv->gc, drv->img, 0, y1, 0, y1, mode.x, height); } mainBuffer.dirty = false; } @@ -393,6 +397,8 @@ static inline void update_display_window_vosf(driver_window *drv) #if REAL_ADDRESSING || DIRECT_ADDRESSING static inline void update_display_dga_vosf(void) { + const video_mode &mode = drv->monitor.get_current_mode(); + int page = 0; for (;;) { const unsigned first_page = find_next_page_set(page); @@ -411,13 +417,13 @@ static inline void update_display_dga_vosf(void) const int y1 = mainBuffer.pageInfo[first_page].top; const int y2 = mainBuffer.pageInfo[page - 1].bottom; - const int bytes_per_row = VideoMonitor.mode.bytes_per_row; - const int bytes_per_pixel = VideoMonitor.mode.bytes_per_row / VideoMonitor.mode.x; + const int bytes_per_row = mode.bytes_per_row; + const int bytes_per_pixel = mode.bytes_per_row / mode.x; int i, j; // Check for first column from left and first column // from right that have changed - int x1 = VideoMonitor.mode.x * bytes_per_pixel - 1; + int x1 = mode.x * bytes_per_pixel - 1; for (j = y1; j <= y2; j++) { uint8 * const p1 = &the_buffer[j * bytes_per_row]; uint8 * const p2 = &the_buffer_copy[j * bytes_per_row]; @@ -434,7 +440,7 @@ static inline void update_display_dga_vosf(void) for (j = y2; j >= y1; j--) { uint8 * const p1 = &the_buffer[j * bytes_per_row]; uint8 * const p2 = &the_buffer_copy[j * bytes_per_row]; - for (i = VideoMonitor.mode.x * bytes_per_pixel - 1; i > x2; i--) { + for (i = mode.x * bytes_per_pixel - 1; i > x2; i--) { if (p1[i] != p2[i]) { x2 = i; break; diff --git a/BasiliskII/src/Unix/video_x.cpp b/BasiliskII/src/Unix/video_x.cpp index be3d25e0..1db183ed 100644 --- a/BasiliskII/src/Unix/video_x.cpp +++ b/BasiliskII/src/Unix/video_x.cpp @@ -39,10 +39,6 @@ #include -#ifndef NO_STD_NAMESPACE -using std::sort; -#endif - #ifdef HAVE_PTHREADS # include #endif @@ -71,6 +67,9 @@ using std::sort; #include "debug.h" +// Supported video modes +static vector VideoModes; + // Display types enum { DISPLAY_WINDOW, // X11 window, using MIT SHM extensions if possible @@ -140,8 +139,8 @@ static int rshift, rloss, gshift, gloss, bshift, bloss; // Pixel format of Direc static Colormap cmap[2] = {0, 0}; // Colormaps for indexed modes (DGA needs two of them) -static XColor palette[256]; // Color palette to be used as CLUT and gamma table -static bool palette_changed = false; // Flag: Palette changed, redraw thread must set new colors +static XColor x_palette[256]; // Color palette to be used as CLUT and gamma table +static bool x_palette_changed = false; // Flag: Palette changed, redraw thread must set new colors #ifdef ENABLE_FBDEV_DGA static int fbdev_fd = -1; @@ -154,9 +153,9 @@ static int num_x_video_modes; // Mutex to protect palette #ifdef HAVE_PTHREADS -static pthread_mutex_t palette_lock = PTHREAD_MUTEX_INITIALIZER; -#define LOCK_PALETTE pthread_mutex_lock(&palette_lock) -#define UNLOCK_PALETTE pthread_mutex_unlock(&palette_lock) +static pthread_mutex_t x_palette_lock = PTHREAD_MUTEX_INITIALIZER; +#define LOCK_PALETTE pthread_mutex_lock(&x_palette_lock) +#define UNLOCK_PALETTE pthread_mutex_unlock(&x_palette_lock) #else #define LOCK_PALETTE #define UNLOCK_PALETTE @@ -194,6 +193,23 @@ extern Display *x_display; extern void SysMountFirstFloppy(void); +/* + * monitor_desc subclass for X11 display + */ + +class X11_monitor_desc : public monitor_desc { +public: + X11_monitor_desc(const vector &available_modes, video_depth default_depth, uint32 default_id) : monitor_desc(available_modes, default_depth, default_id) {} + ~X11_monitor_desc() {} + + virtual void switch_to_current_mode(void); + virtual void set_palette(uint8 *pal, int num); + + bool video_open(void); + void video_close(void); +}; + + /* * Utility functions */ @@ -332,7 +348,7 @@ static void add_window_modes(video_depth depth) } // Set Mac frame layout and base address (uses the_buffer/MacFrameBaseMac) -static void set_mac_frame_buffer(video_depth depth, bool native_byte_order) +static void set_mac_frame_buffer(X11_monitor_desc &monitor, video_depth depth, bool native_byte_order) { #if !REAL_ADDRESSING && !DIRECT_ADDRESSING int layout = FLAYOUT_DIRECT; @@ -344,16 +360,17 @@ static void set_mac_frame_buffer(video_depth depth, bool native_byte_order) MacFrameLayout = layout; else MacFrameLayout = FLAYOUT_DIRECT; - VideoMonitor.mac_frame_base = MacFrameBaseMac; + monitor.set_mac_frame_base(MacFrameBaseMac); // Set variables used by UAE memory banking + const video_mode &mode = monitor.get_current_mode(); MacFrameBaseHost = the_buffer; - MacFrameSize = VideoMonitor.mode.bytes_per_row * VideoMonitor.mode.y; + MacFrameSize = mode.bytes_per_row * mode.y; InitFrameBufferMapping(); #else - VideoMonitor.mac_frame_base = Host2MacAddr(the_buffer); + monitor.set_mac_frame_base(Host2MacAddr(the_buffer)); #endif - D(bug("VideoMonitor.mac_frame_base = %08x\n", VideoMonitor.mac_frame_base)); + D(bug("monitor.mac_frame_base = %08x\n", monitor.get_mac_frame_base())); } // Set window name and class @@ -431,7 +448,7 @@ static int error_handler(Display *d, XErrorEvent *e) class driver_base { public: - driver_base(); + driver_base(X11_monitor_desc &m); virtual ~driver_base(); virtual void update_palette(void); @@ -447,6 +464,9 @@ public: virtual void ungrab_mouse(void) {} public: + X11_monitor_desc &monitor; // Associated video monitor + const video_mode &mode; // Video mode handled by the driver + bool init_ok; // Initialization succeeded (we can't use exceptions because of -fomit-frame-pointer) Window w; // The window we draw into @@ -464,7 +484,7 @@ class driver_window : public driver_base { friend void update_display_static(driver_window *drv); public: - driver_window(const video_mode &mode); + driver_window(X11_monitor_desc &monitor); ~driver_window(); void toggle_mouse_grab(void); @@ -489,8 +509,8 @@ static driver_base *drv = NULL; // Pointer to currently used driver object # include "video_vosf.h" #endif -driver_base::driver_base() - : init_ok(false), w(0) +driver_base::driver_base(X11_monitor_desc &m) + : monitor(m), mode(m.get_current_mode()), init_ok(false), w(0) { the_buffer = NULL; the_buffer_copy = NULL; @@ -549,10 +569,10 @@ void driver_base::update_palette(void) { if (color_class == PseudoColor || color_class == DirectColor) { int num = vis->map_entries; - if (!IsDirectMode(VideoMonitor.mode) && color_class == DirectColor) + if (!IsDirectMode(monitor.get_current_mode()) && color_class == DirectColor) return; // Indexed mode on true color screen, don't set CLUT - XStoreColors(x_display, cmap[0], palette, num); - XStoreColors(x_display, cmap[1], palette, num); + XStoreColors(x_display, cmap[0], x_palette, num); + XStoreColors(x_display, cmap[1], x_palette, num); } XSync(x_display, false); } @@ -575,8 +595,8 @@ void driver_base::restore_mouse_accel(void) */ // Open display -driver_window::driver_window(const video_mode &mode) - : gc(0), img(NULL), have_shm(false), mac_cursor(0), mouse_grabbed(false) +driver_window::driver_window(X11_monitor_desc &m) + : driver_base(m), gc(0), img(NULL), have_shm(false), mac_cursor(0), mouse_grabbed(false) { int width = mode.x, height = mode.y; int aligned_width = (width + 15) & ~15; @@ -708,9 +728,8 @@ driver_window::driver_window(const video_mode &mode) Screen_blitter_init(&visualInfo, native_byte_order, mode.depth); #endif - // Set VideoMonitor - VideoMonitor.mode = mode; - set_mac_frame_buffer(mode.depth, native_byte_order); + // Set frame buffer base + set_mac_frame_buffer(monitor, mode.depth, native_byte_order); // Everything went well init_ok = true; @@ -790,7 +809,7 @@ void driver_window::mouse_moved(int x, int y) // Warped mouse motion (this code is taken from SDL) // Post first mouse event - int width = VideoMonitor.mode.x, height = VideoMonitor.mode.y; + int width = monitor.get_current_mode().x, height = monitor.get_current_mode().y; int delta_x = x - mouse_last_x, delta_y = y - mouse_last_y; mouse_last_x = x; mouse_last_y = y; ADBMouseMoved(delta_x, delta_y); @@ -827,7 +846,7 @@ void driver_window::mouse_moved(int x, int y) class driver_dga : public driver_base { public: - driver_dga(); + driver_dga(X11_monitor_desc &monitor); ~driver_dga(); void suspend(void); @@ -838,8 +857,8 @@ private: void *fb_save; // Saved frame buffer for suspend/resume }; -driver_dga::driver_dga() - : suspend_win(0), fb_save(NULL) +driver_dga::driver_dga(X11_monitor_desc &m) + : driver_base(m), suspend_win(0), fb_save(NULL) { } @@ -860,9 +879,9 @@ void driver_dga::suspend(void) LOCK_FRAME_BUFFER; // Save frame buffer - fb_save = malloc(VideoMonitor.mode.y * VideoMonitor.mode.bytes_per_row); + fb_save = malloc(mode.y * mode.bytes_per_row); if (fb_save) - memcpy(fb_save, the_buffer, VideoMonitor.mode.y * VideoMonitor.mode.bytes_per_row); + memcpy(fb_save, the_buffer, mode.y * mode.bytes_per_row); // Close full screen display #ifdef ENABLE_XF86_DGA @@ -915,7 +934,7 @@ void driver_dga::resume(void) LOCK_VOSF; PFLAG_SET_ALL; UNLOCK_VOSF; - memset(the_buffer_copy, 0, VideoMonitor.mode.bytes_per_row * VideoMonitor.mode.y); + memset(the_buffer_copy, 0, mode.bytes_per_row * mode.y); } #endif @@ -925,7 +944,7 @@ void driver_dga::resume(void) // Don't copy fb_save to the temporary frame buffer in VOSF mode if (!use_vosf) #endif - memcpy(the_buffer, fb_save, VideoMonitor.mode.y * VideoMonitor.mode.bytes_per_row); + memcpy(the_buffer, fb_save, mode.y * mode.bytes_per_row); free(fb_save); fb_save = NULL; } @@ -947,12 +966,12 @@ const char FBDEVICE_FILE_NAME[] = "/dev/fb"; class driver_fbdev : public driver_dga { public: - driver_fbdev(const video_mode &mode); + driver_fbdev(X11_monitor_desc &monitor); ~driver_fbdev(); }; // Open display -driver_fbdev::driver_fbdev(const video_mode &mode) +driver_fbdev::driver_fbdev(X11_monitor_desc &m) : driver_dga(m) { int width = mode.x, height = mode.y; @@ -1081,10 +1100,9 @@ driver_fbdev::driver_fbdev(const video_mode &mode) #endif #endif - // Set VideoMonitor - VideoModes[0].bytes_per_row = bytes_per_row; - VideoModes[0].depth = DepthModeForPixelDepth(fb_depth); - VideoMonitor.mode = mode; + // Set frame buffer base + const_cast(&mode)->bytes_per_row = bytes_per_row; + const_cast(&mode)->depth = DepthModeForPixelDepth(fb_depth); set_mac_frame_buffer(mode.depth, true); // Everything went well @@ -1121,7 +1139,7 @@ driver_fbdev::~driver_fbdev() class driver_xf86dga : public driver_dga { public: - driver_xf86dga(const video_mode &mode); + driver_xf86dga(X11_monitor_desc &monitor); ~driver_xf86dga(); void update_palette(void); @@ -1132,8 +1150,8 @@ private: }; // Open display -driver_xf86dga::driver_xf86dga(const video_mode &mode) - : current_dga_cmap(0) +driver_xf86dga::driver_xf86dga(X11_monitor_desc &m) + : driver_dga(m), current_dga_cmap(0) { int width = mode.x, height = mode.y; @@ -1214,10 +1232,9 @@ driver_xf86dga::driver_xf86dga(const video_mode &mode) #endif #endif - // Set VideoMonitor + // Set frame buffer base const_cast(&mode)->bytes_per_row = bytes_per_row; - VideoMonitor.mode = mode; - set_mac_frame_buffer(mode.depth, true); + set_mac_frame_buffer(monitor, mode.depth, true); // Everything went well init_ok = true; @@ -1248,7 +1265,7 @@ void driver_xf86dga::update_palette(void) { driver_dga::update_palette(); current_dga_cmap ^= 1; - if (!IsDirectMode(VideoMonitor.mode) && cmap[current_dga_cmap]) + if (!IsDirectMode(monitor.get_current_mode()) && cmap[current_dga_cmap]) XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]); } @@ -1256,7 +1273,7 @@ void driver_xf86dga::update_palette(void) void driver_xf86dga::resume(void) { driver_dga::resume(); - if (!IsDirectMode(VideoMonitor.mode)) + if (!IsDirectMode(monitor.get_current_mode())) XF86DGAInstallColormap(x_display, screen, cmap[current_dga_cmap]); } #endif @@ -1331,10 +1348,11 @@ static void keycode_init(void) } } -// Open display for specified mode -static bool video_open(const video_mode &mode) +// Open display for current mode +bool X11_monitor_desc::video_open(void) { D(bug("video_open()\n")); + const video_mode &mode = get_current_mode(); // Find best available X visual if (!find_visual_for_depth(mode.depth)) { @@ -1375,13 +1393,13 @@ static bool video_open(const video_mode &mode) int num = vis->map_entries; for (int i=0; imap_entries : 256); for (int i=0; i::const_iterator i, end = VideoModes.end(); + for (i = VideoModes.begin(); i != end; ++i) { + if (i->x == default_width && i->y == default_height && i->depth == default_depth) { + default_id = i->resolution_id; + break; + } + } + if (i == end) { // not found, use first available mode + default_depth = VideoModes[0].depth; + default_id = VideoModes[0].resolution_id; + } #if DEBUG D(bug("Available video modes:\n")); - vector::const_iterator i = VideoModes.begin(), end = VideoModes.end(); - while (i != end) { + for (i = VideoModes.begin(); i != end; ++i) { int bits = 1 << i->depth; if (bits == 16) bits = 15; else if (bits == 32) bits = 24; D(bug(" %dx%d (ID %02x), %d colors\n", i->x, i->y, i->resolution_id, 1 << bits)); - ++i; } #endif - // Find requested default mode and open display - if (VideoModes.size() == 1) - return video_open(VideoModes[0]); - else { - // Find mode with specified dimensions - std::vector::const_iterator i, end = VideoModes.end(); - for (i = VideoModes.begin(); i != end; ++i) { - if (i->x == default_width && i->y == default_height && i->depth == default_depth) - return video_open(*i); - } - return video_open(VideoModes[0]); - } + // Create X11_monitor_desc for this (the only) display + X11_monitor_desc *monitor = new X11_monitor_desc(VideoModes, default_depth, default_id); + VideoMonitors.push_back(monitor); + + // Open display + return monitor->video_open(); } @@ -1633,7 +1656,7 @@ bool VideoInit(bool classic) */ // Close display -static void video_close(void) +void X11_monitor_desc::video_close(void) { D(bug("video_close()\n")); @@ -1678,8 +1701,10 @@ static void video_close(void) void VideoExit(void) { - // Close display - video_close(); + // Close displays + vector::iterator i, end = VideoMonitors.end(); + for (i = VideoMonitors.begin(); i != end; ++i) + dynamic_cast(*i)->video_close(); #ifdef ENABLE_XF86_VIDMODE // Free video mode list @@ -1737,19 +1762,21 @@ void VideoInterrupt(void) * Set palette */ -void video_set_palette(uint8 *pal, int num_in) +void X11_monitor_desc::set_palette(uint8 *pal, int num_in) { + const video_mode &mode = get_current_mode(); + LOCK_PALETTE; // Convert colors to XColor array int num_out = 256; bool stretch = false; - if (IsDirectMode(VideoMonitor.mode)) { + if (IsDirectMode(mode)) { // If X is in 565 mode we have to stretch the gamma table from 32 to 64 entries num_out = vis->map_entries; stretch = true; } - XColor *p = palette; + XColor *p = x_palette; for (int i=0; ired = pal[c*3 + 0] * 0x0101; @@ -1760,7 +1787,7 @@ void video_set_palette(uint8 *pal, int num_in) #ifdef ENABLE_VOSF // Recalculate pixel color expansion map - if (!IsDirectMode(VideoMonitor.mode) && xdepth > 8) { + if (!IsDirectMode(mode) && xdepth > 8) { for (int i=0; i<256; i++) { int c = i & (num_in-1); // If there are less than 256 colors, we repeat the first entries (this makes color expansion easier) ExpandMap[i] = map_rgb(pal[c*3+0], pal[c*3+1], pal[c*3+2]); @@ -1770,12 +1797,12 @@ void video_set_palette(uint8 *pal, int num_in) LOCK_VOSF; PFLAG_SET_ALL; UNLOCK_VOSF; - memset(the_buffer_copy, 0, VideoMonitor.mode.bytes_per_row * VideoMonitor.mode.y); + memset(the_buffer_copy, 0, mode.bytes_per_row * mode.y); } #endif // Tell redraw thread to change palette - palette_changed = true; + x_palette_changed = true; UNLOCK_PALETTE; } @@ -1785,11 +1812,11 @@ void video_set_palette(uint8 *pal, int num_in) * Switch video mode */ -void video_switch_to_mode(const video_mode &mode) +void X11_monitor_desc::switch_to_current_mode(void) { // Close and reopen display video_close(); - video_open(mode); + video_open(); if (drv == NULL) { ErrorAlert(STR_OPEN_WINDOW_ERR); @@ -2059,12 +2086,13 @@ static void handle_events(void) // Hidden parts exposed, force complete refresh of window case Expose: if (display_type == DISPLAY_WINDOW) { + const video_mode &mode = VideoMonitors[0]->get_current_mode(); #ifdef ENABLE_VOSF if (use_vosf) { // VOSF refresh LOCK_VOSF; PFLAG_SET_ALL; UNLOCK_VOSF; - memset(the_buffer_copy, 0, VideoMonitor.mode.bytes_per_row * VideoMonitor.mode.y); + memset(the_buffer_copy, 0, mode.bytes_per_row * mode.y); } else #endif @@ -2075,7 +2103,7 @@ static void handle_events(void) updt_box[x1][y1] = true; nr_boxes = 16 * 16; } else // Static refresh - memset(the_buffer_copy, 0, VideoMonitor.mode.bytes_per_row * VideoMonitor.mode.y); + memset(the_buffer_copy, 0, mode.bytes_per_row * mode.y); } break; @@ -2101,10 +2129,11 @@ static void update_display_dynamic(int ticker, driver_window *drv) int y1, y2, y2s, y2a, i, x1, xm, xmo, ymo, yo, yi, yil, xi; int xil = 0; int rxm = 0, rxmo = 0; - int bytes_per_row = VideoMonitor.mode.bytes_per_row; - int bytes_per_pixel = VideoMonitor.mode.bytes_per_row / VideoMonitor.mode.x; - int rx = VideoMonitor.mode.bytes_per_row / 16; - int ry = VideoMonitor.mode.y / 16; + const video_mode &mode = drv->monitor.get_current_mode(); + int bytes_per_row = mode.bytes_per_row; + int bytes_per_pixel = mode.bytes_per_row / mode.x; + int rx = mode.bytes_per_row / 16; + int ry = mode.y / 16; int max_box; y2s = sm_uptd[ticker % 8]; @@ -2158,7 +2187,7 @@ static void update_display_dynamic(int ticker, driver_window *drv) i = (yi * bytes_per_row) + xi; for (y2=0; y2 < yil; y2++, i += bytes_per_row) memcpy(&the_buffer_copy[i], &the_buffer[i], xil); - if (VideoMonitor.mode.depth == VDEPTH_1BIT) { + if (mode.depth == VDEPTH_1BIT) { if (drv->have_shm) XShmPutImage(x_display, drv->w, drv->gc, drv->img, xi * 8, yi, xi * 8, yi, xil * 8, yil, 0); else @@ -2190,20 +2219,21 @@ static void update_display_static(driver_window *drv) { // Incremental update code unsigned wide = 0, high = 0, x1, x2, y1, y2, i, j; - int bytes_per_row = VideoMonitor.mode.bytes_per_row; - int bytes_per_pixel = VideoMonitor.mode.bytes_per_row / VideoMonitor.mode.x; + const video_mode &mode = drv->monitor.get_current_mode(); + int bytes_per_row = mode.bytes_per_row; + int bytes_per_pixel = mode.bytes_per_row / mode.x; uint8 *p, *p2; // Check for first line from top and first line from bottom that have changed y1 = 0; - for (j=0; j=y1; j--) { + for (j=mode.y-1; j>=y1; j--) { if (memcmp(&the_buffer[j * bytes_per_row], &the_buffer_copy[j * bytes_per_row], bytes_per_row)) { y2 = j; break; @@ -2213,8 +2243,8 @@ static void update_display_static(driver_window *drv) // Check for first column from left and first column from right that have changed if (high) { - if (VideoMonitor.mode.depth == VDEPTH_1BIT) { - x1 = VideoMonitor.mode.x - 1; + if (mode.depth == VDEPTH_1BIT) { + x1 = mode.x - 1; for (j=y1; j<=y2; j++) { p = &the_buffer[j * bytes_per_row]; p2 = &the_buffer_copy[j * bytes_per_row]; @@ -2232,7 +2262,7 @@ static void update_display_static(driver_window *drv) p2 = &the_buffer_copy[j * bytes_per_row]; p += bytes_per_row; p2 += bytes_per_row; - for (i=(VideoMonitor.mode.x>>3); i>(x2>>3); i--) { + for (i=(mode.x>>3); i>(x2>>3); i--) { p--; p2--; if (*p != *p2) { x2 = (i << 3) + 7; @@ -2251,7 +2281,7 @@ static void update_display_static(driver_window *drv) } } else { - x1 = VideoMonitor.mode.x; + x1 = mode.x; for (j=y1; j<=y2; j++) { p = &the_buffer[j * bytes_per_row]; p2 = &the_buffer_copy[j * bytes_per_row]; @@ -2269,7 +2299,7 @@ static void update_display_static(driver_window *drv) p2 = &the_buffer_copy[j * bytes_per_row]; p += bytes_per_row; p2 += bytes_per_row; - for (i=VideoMonitor.mode.x*bytes_per_pixel; i>x2*bytes_per_pixel; i--) { + for (i=mode.x*bytes_per_pixel; i>x2*bytes_per_pixel; i--) { p--; p2--; if (*p != *p2) { @@ -2336,8 +2366,8 @@ static inline void handle_palette_changes(void) { LOCK_PALETTE; - if (palette_changed) { - palette_changed = false; + if (x_palette_changed) { + x_palette_changed = false; drv->update_palette(); } diff --git a/BasiliskII/src/include/video.h b/BasiliskII/src/include/video.h index 39696e46..ad4df821 100644 --- a/BasiliskII/src/include/video.h +++ b/BasiliskII/src/include/video.h @@ -27,6 +27,7 @@ using std::vector; #endif + /* Some of the terminology here is completely frelled. In Basilisk II, a "video mode" refers to a combination of resolution and color depth, and @@ -55,19 +56,7 @@ enum video_depth { VDEPTH_32BIT // "Millions" }; -// For compatibility reasons with older (pre-Display Manager) versions of -// MacOS, the Apple modes must start at 0x80 and be contiguous. Therefore -// we construct an array to map the depth codes to the corresponding Apple -// mode. This array is initialized by video_init_depth_list() which must -// be called by the platform-dependant VideoInit() routine after filling -// the VideoModes array. -extern uint16 apple_mode_for_depth[6]; - -inline uint16 DepthToAppleMode(video_depth depth) -{ - return apple_mode_for_depth[depth]; -} - +// 1, 2, 4 and 8 bit depths use a color palette inline bool IsDirectMode(video_depth depth) { return depth == VDEPTH_16BIT || depth == VDEPTH_32BIT; @@ -101,6 +90,7 @@ inline uint32 TrivialBytesPerRow(uint32 width, video_depth depth) } } + /* You are not completely free in your selection of depth/resolution combinations: @@ -134,8 +124,9 @@ struct video_mode { uint32 x; // X size of screen (pixels) uint32 y; // Y size of screen (pixels) uint32 resolution_id; // Resolution ID (should be >= 0x80 and uniquely identify the sets of modes with the same X/Y size) - uint32 bytes_per_row; // Bytes per row of frame buffer video_depth depth; // Color depth (see definitions above) + uint32 bytes_per_row; // Bytes per row of frame buffer + uint32 user_data; // Free for use by platform-specific code }; inline bool IsDirectMode(const video_mode &mode) @@ -143,22 +134,132 @@ inline bool IsDirectMode(const video_mode &mode) return IsDirectMode(mode.depth); } -// List of all supported video modes -extern vector VideoModes; -// Description for one (possibly virtual) monitor -struct monitor_desc { - uint32 mac_frame_base; // Mac frame buffer address - video_mode mode; // Currently selected video mode description +// Mac video driver per-display private variables (opaque) +struct video_locals; + + +// Abstract base class representing one (possibly virtual) monitor +// ("monitor" = rectangular display with a contiguous frame buffer) +class monitor_desc { +public: + monitor_desc(const vector &available_modes, video_depth default_depth, uint32 default_id); + virtual ~monitor_desc() {} + + // Get Mac slot ID number + uint8 get_slot_id(void) const {return slot_id;} + + // Get current Mac frame buffer base address + uint32 get_mac_frame_base(void) const {return mac_frame_base;} + + // Set Mac frame buffer base address (called from switch_to_mode()) + void set_mac_frame_base(uint32 base) {mac_frame_base = base;} + + // Get current video mode + const video_mode &get_current_mode(void) const {return *current_mode;} + + // Get Apple mode id for given depth + uint16 depth_to_apple_mode(video_depth depth) const {return apple_mode_for_depth[depth];} + + // Get current color depth + uint16 get_apple_mode(void) const {return depth_to_apple_mode(current_mode->depth);} + + // Get bytes-per-row value for specified resolution/depth + // (if the mode isn't supported, make a good guess) + uint32 get_bytes_per_row(video_depth depth, uint32 id) const; + + // Check whether a mode with the specified depth exists on this display + bool has_depth(video_depth depth) const; + + // Mac video driver functions + int16 driver_open(void); + int16 driver_control(uint16 code, uint32 param, uint32 dce); + int16 driver_status(uint16 code, uint32 param); + +protected: + vector modes; // List of supported video modes + vector::const_iterator current_mode; // Currently selected video mode + + uint32 mac_frame_base; // Mac frame buffer address for current mode + +// Mac video driver per-display private variables/functions +private: + // Check whether the specified resolution ID is one of the supported resolutions + bool has_resolution(uint32 id) const; + + // Return iterator signifying "invalid mode" + vector::const_iterator invalid_mode(void) const {return modes.end();} + + // Find specified mode (depth/resolution) (or invalid_mode() if not found) + vector::const_iterator find_mode(uint16 apple_mode, uint32 id) const; + + // Find maximum supported depth for given resolution ID + video_depth max_depth_of_resolution(uint32 id) const; + + // Get X/Y size of specified resolution + void get_size_of_resolution(uint32 id, uint32 &x, uint32 &y) const; + + // Set palette to 50% gray + void set_gray_palette(void); + + // Load gamma-corrected black-to-white ramp to palette for direct-color mode + void load_ramp_palette(void); + + // Allocate gamma table of specified size + bool allocate_gamma_table(int size); + + // Set gamma table (0 = build linear ramp) + bool set_gamma_table(uint32 user_table); + + // Switch video mode + void switch_mode(vector::const_iterator it, uint32 param, uint32 dce); + + uint8 slot_id; // NuBus slot ID number + static uint8 next_slot_id; // Next available slot ID + + uint8 palette[256 * 3]; // Color palette, 256 entries, RGB + + bool luminance_mapping; // Luminance mapping on/off + bool interrupts_enabled; // VBL interrupts on/off + bool dm_present; // We received a GetVideoParameters call, so the Display Manager seems to be present + + uint32 gamma_table; // Mac address of gamma table + int alloc_gamma_table_size; // Allocated size of gamma table + + uint16 current_apple_mode; // Currently selected depth/resolution + uint32 current_id; + uint16 preferred_apple_mode; // Preferred depth/resolution + uint32 preferred_id; + + uint32 slot_param; // Mac address of Slot Manager parameter block + + // For compatibility reasons with older (pre-Display Manager) versions of + // MacOS, the Apple modes must start at 0x80 and be contiguous. Therefore + // we maintain an array to map the depth codes to the corresponding Apple + // mode. + uint16 apple_mode_for_depth[6]; + +// The following functions are implemented by platform-specific code +public: + + // Called by the video driver to switch the video mode on this display + // (must call set_mac_frame_base()) + virtual void switch_to_current_mode(void) = 0; + + // Called by the video driver to set the color palette (in indexed modes) + // or the gamma table (in direct modes) + virtual void set_palette(uint8 *pal, int num) = 0; }; -// Description of the main (and currently the only) monitor, set by VideoInit() -extern monitor_desc VideoMonitor; +// Vector of pointers to available monitor descriptions, filled by VideoInit() +extern vector VideoMonitors; + extern int16 VideoDriverOpen(uint32 pb, uint32 dce); extern int16 VideoDriverControl(uint32 pb, uint32 dce); extern int16 VideoDriverStatus(uint32 pb, uint32 dce); + // System specific and internal functions/data extern bool VideoInit(bool classic); extern void VideoExit(void); @@ -168,20 +269,4 @@ extern void VideoQuitFullScreen(void); extern void VideoInterrupt(void); extern void VideoRefresh(void); -// Called by the video driver to switch the video mode -extern void video_switch_to_mode(const video_mode &mode); - -// Called by the video driver to set the color palette (in indexed modes) -// or gamma table (in direct modes) -extern void video_set_palette(uint8 *pal, int num); - -// Check whether a mode with the specified depth exists -extern bool video_has_depth(video_depth depth); - -// Get bytes-per-row value for specified resolution/depth -extern uint32 video_bytes_per_row(video_depth depth, uint32 id); - -// Initialize apple_mode_for_depth[] array from VideoModes list -extern void video_init_depth_list(void); - #endif diff --git a/BasiliskII/src/main.cpp b/BasiliskII/src/main.cpp index bb499057..eff8474e 100644 --- a/BasiliskII/src/main.cpp +++ b/BasiliskII/src/main.cpp @@ -176,7 +176,8 @@ bool InitAll(void) // Set default video mode in XPRAM XPRAM[0x56] = 0x42; // 'B' XPRAM[0x57] = 0x32; // '2' - XPRAM[0x58] = DepthToAppleMode(VideoMonitor.mode.depth); + const monitor_desc &main_monitor = *VideoMonitors[0]; + XPRAM[0x58] = main_monitor.depth_to_apple_mode(main_monitor.get_current_mode().depth); XPRAM[0x59] = 0; #if EMULATED_68K diff --git a/BasiliskII/src/slot_rom.cpp b/BasiliskII/src/slot_rom.cpp index e6092714..03fe11b8 100644 --- a/BasiliskII/src/slot_rom.cpp +++ b/BasiliskII/src/slot_rom.cpp @@ -105,12 +105,14 @@ static void PString(char *str) srom[p++] = 0; } -static uint32 VModeParms(const video_mode &mode, video_depth depth) +static uint32 VModeParms(const monitor_desc &m, video_depth depth) { + const video_mode &mode = m.get_current_mode(); + uint32 ret = p; Long(50); // Length Long(0); // Base offset - Word(video_bytes_per_row(depth, mode.resolution_id)); + Word(m.get_bytes_per_row(depth, mode.resolution_id)); Word(0); // Bounds Word(0); Word(mode.y); @@ -173,15 +175,64 @@ static uint32 VModeDesc(uint32 params, bool direct) return ret; } +static uint32 VMonitor(const monitor_desc &m, uint32 videoType, uint32 videoName, uint32 vidDrvrDir, uint32 gammaDir) +{ + uint32 minorBase, minorLength; + uint32 vidModeParms1, vidModeParms2, vidModeParms4, vidModeParms8, vidModeParms16, vidModeParms32; + uint32 vidMode1, vidMode2, vidMode4, vidMode8, vidMode16, vidMode32; + uint32 ret; + + minorBase = p; + Long(m.get_mac_frame_base()); // Frame buffer base + minorLength = p; + Long(0); // Frame buffer size (unspecified) + + vidModeParms1 = VModeParms(m, VDEPTH_1BIT); + vidModeParms2 = VModeParms(m, VDEPTH_2BIT); + vidModeParms4 = VModeParms(m, VDEPTH_4BIT); + vidModeParms8 = VModeParms(m, VDEPTH_8BIT); + vidModeParms16 = VModeParms(m, VDEPTH_16BIT); + vidModeParms32 = VModeParms(m, VDEPTH_32BIT); + + vidMode1 = VModeDesc(vidModeParms1, false); + vidMode2 = VModeDesc(vidModeParms2, false); + vidMode4 = VModeDesc(vidModeParms4, false); + vidMode8 = VModeDesc(vidModeParms8, false); + vidMode16 = VModeDesc(vidModeParms16, true); + vidMode32 = VModeDesc(vidModeParms32, true); + + ret = p; + Offs(0x01, videoType); // Video type descriptor + Offs(0x02, videoName); // Driver name + Offs(0x04, vidDrvrDir); // Driver directory + Rsrc(0x08, 0x4232); // Hardware device ID ('B2') + Offs(0x0a, minorBase); // Frame buffer base + Offs(0x0b, minorLength); // Frame buffer length + Offs(0x40, gammaDir); // Gamma directory + Rsrc(0x7d, 6); // Video attributes: Default to color, built-in + if (m.has_depth(VDEPTH_1BIT)) + Offs(m.depth_to_apple_mode(VDEPTH_1BIT), vidMode1); // Video mode parameters for 1 bit + if (m.has_depth(VDEPTH_2BIT)) + Offs(m.depth_to_apple_mode(VDEPTH_2BIT), vidMode2); // Video mode parameters for 2 bit + if (m.has_depth(VDEPTH_4BIT)) + Offs(m.depth_to_apple_mode(VDEPTH_4BIT), vidMode4); // Video mode parameters for 4 bit + if (m.has_depth(VDEPTH_8BIT)) + Offs(m.depth_to_apple_mode(VDEPTH_8BIT), vidMode8); // Video mode parameters for 8 bit + if (m.has_depth(VDEPTH_16BIT)) + Offs(m.depth_to_apple_mode(VDEPTH_16BIT), vidMode16); // Video mode parameters for 16 bit + if (m.has_depth(VDEPTH_32BIT)) + Offs(m.depth_to_apple_mode(VDEPTH_32BIT), vidMode32); // Video mode parameters for 32 bit + EndOfList(); + return ret; +} + bool InstallSlotROM(void) { uint32 boardType, boardName, vendorID, revLevel, partNum, date; uint32 vendorInfo, sRsrcBoard; - uint32 videoType, videoName, minorBase, minorLength, videoDrvr, vidDrvrDir; - uint32 defaultGamma, gammaDir, sRsrcVideo; - uint32 vidModeParms1, vidModeParms2, vidModeParms4, vidModeParms8, vidModeParms16, vidModeParms32; - uint32 vidMode1, vidMode2, vidMode4, vidMode8, vidMode16, vidMode32; + uint32 videoType, videoName, videoDrvr, vidDrvrDir; + uint32 defaultGamma, gammaDir; uint32 cpuType, cpuName, cpuMajor, cpuMinor, sRsrcCPU; @@ -189,7 +240,11 @@ bool InstallSlotROM(void) uint32 sRsrcDir; + vector::const_iterator m, mend = VideoMonitors.end(); + vector sRsrcVideo; + char str[256]; + int i; p = 0; // Board sResource @@ -221,15 +276,10 @@ bool InstallSlotROM(void) Offs(0x24, vendorInfo); // Vendor Info EndOfList(); - // Video sResource for default mode - videoType = p; // Literals + videoType = p; Word(3); Word(1); Word(1); Word(0x4232); // Display Video Apple 'B2' videoName = p; String("Display_Video_Apple_Basilisk"); - minorBase = p; - Long(VideoMonitor.mac_frame_base); // Frame buffer base - minorLength = p; - Long(0); // Frame buffer size (unspecified) videoDrvr = p; // Video driver Long(0x72); // Length @@ -302,42 +352,8 @@ bool InstallSlotROM(void) Offs(0x80, defaultGamma); EndOfList(); - vidModeParms1 = VModeParms(VideoMonitor.mode, VDEPTH_1BIT); - vidModeParms2 = VModeParms(VideoMonitor.mode, VDEPTH_2BIT); - vidModeParms4 = VModeParms(VideoMonitor.mode, VDEPTH_4BIT); - vidModeParms8 = VModeParms(VideoMonitor.mode, VDEPTH_8BIT); - vidModeParms16 = VModeParms(VideoMonitor.mode, VDEPTH_16BIT); - vidModeParms32 = VModeParms(VideoMonitor.mode, VDEPTH_32BIT); - - vidMode1 = VModeDesc(vidModeParms1, false); - vidMode2 = VModeDesc(vidModeParms2, false); - vidMode4 = VModeDesc(vidModeParms4, false); - vidMode8 = VModeDesc(vidModeParms8, false); - vidMode16 = VModeDesc(vidModeParms16, true); - vidMode32 = VModeDesc(vidModeParms32, true); - - sRsrcVideo = p; - Offs(0x01, videoType); // Video type descriptor - Offs(0x02, videoName); // Driver name - Offs(0x04, vidDrvrDir); // Driver directory - Rsrc(0x08, 0x4232); // Hardware device ID ('B2') - Offs(0x0a, minorBase); // Frame buffer base - Offs(0x0b, minorLength); // Frame buffer length - Offs(0x40, gammaDir); // Gamma directory - Rsrc(0x7d, 6); // Video attributes: Default to color, built-in - if (video_has_depth(VDEPTH_1BIT)) - Offs(DepthToAppleMode(VDEPTH_1BIT), vidMode1); // Video mode parameters for 1 bit - if (video_has_depth(VDEPTH_2BIT)) - Offs(DepthToAppleMode(VDEPTH_2BIT), vidMode2); // Video mode parameters for 2 bit - if (video_has_depth(VDEPTH_4BIT)) - Offs(DepthToAppleMode(VDEPTH_4BIT), vidMode4); // Video mode parameters for 4 bit - if (video_has_depth(VDEPTH_8BIT)) - Offs(DepthToAppleMode(VDEPTH_8BIT), vidMode8); // Video mode parameters for 8 bit - if (video_has_depth(VDEPTH_16BIT)) - Offs(DepthToAppleMode(VDEPTH_16BIT), vidMode16); // Video mode parameters for 16 bit - if (video_has_depth(VDEPTH_32BIT)) - Offs(DepthToAppleMode(VDEPTH_32BIT), vidMode32); // Video mode parameters for 32 bit - EndOfList(); + for (m = VideoMonitors.begin(); m != mend; ++m) + sRsrcVideo.push_back(VMonitor(**m, videoType, videoName, vidDrvrDir, gammaDir)); // CPU sResource cpuType = p; // Literals @@ -415,7 +431,8 @@ bool InstallSlotROM(void) // sResource directory sRsrcDir = p; Offs(0x01, sRsrcBoard); - Offs(0x80, sRsrcVideo); + for (m = VideoMonitors.begin(), i = 0; m != mend; ++m, ++i) + Offs((*m)->get_slot_id(), sRsrcVideo[i]); Offs(0xf0, sRsrcCPU); Offs(0xf1, sRsrcEther); EndOfList(); diff --git a/BasiliskII/src/video.cpp b/BasiliskII/src/video.cpp index 32f38da3..43d1f1a3 100644 --- a/BasiliskII/src/video.cpp +++ b/BasiliskII/src/video.cpp @@ -41,143 +41,11 @@ #include "debug.h" -// List of supported video modes -vector VideoModes; +// Next available NuBus slot ID +uint8 monitor_desc::next_slot_id = 0x80; -// Description of the main monitor -monitor_desc VideoMonitor; - -// Depth code -> Apple mode mapping -uint16 apple_mode_for_depth[6]; - -// Local variables (per monitor) -struct { - monitor_desc *desc; // Pointer to description of monitor handled by this instance of the driver - uint8 palette[256 * 3]; // Color palette, 256 entries, RGB - bool luminance_mapping; // Luminance mapping on/off - bool interrupts_enabled; // VBL interrupts on/off - bool dm_present; // We received a GetVideoParameters call, so the Display Manager seems to be present - uint32 gamma_table; // Mac address of gamma table - int alloc_gamma_table_size; // Allocated size of gamma table - uint16 current_mode; // Currently selected depth/resolution - uint32 current_id; - uint16 preferred_mode; // Preferred depth/resolution - uint32 preferred_id; - uint32 slot_param; // Mac address of Slot Manager parameter block -} VidLocal; - - -/* - * Initialize apple_mode_for_depth[] array from VideoModes list - */ - -void video_init_depth_list(void) -{ - uint16 mode = 0x80; - for (int depth = VDEPTH_1BIT; depth <= VDEPTH_32BIT; depth++) { - if (video_has_depth(video_depth(depth))) - apple_mode_for_depth[depth] = mode++; - else - apple_mode_for_depth[depth] = 0; - } -} - - -/* - * Check whether a mode with the specified depth exists - */ - -bool video_has_depth(video_depth depth) -{ - vector::const_iterator i = VideoModes.begin(), end = VideoModes.end(); - while (i != end) { - if (i->depth == depth) - return true; - ++i; - } - return false; -} - - -/* - * Check whether specified resolution ID is one of the supported resolutions - */ - -static bool has_resolution(uint32 id) -{ - vector::const_iterator i, end = VideoModes.end(); - for (i = VideoModes.begin(); i != end; ++i) { - if (i->resolution_id == id) - return true; - } - return false; -} - - -/* - * Find specified mode (depth/resolution) (or VideoModes.end() if not found) - */ - -static vector::const_iterator find_mode(uint16 mode, uint32 id) -{ - vector::const_iterator i, end = VideoModes.end(); - for (i = VideoModes.begin(); i != end; ++i) { - if (i->resolution_id == id && DepthToAppleMode(i->depth) == mode) - return i; - } - return i; -} - - -/* - * Find maximum supported depth for given resolution ID - */ - -static video_depth max_depth_of_resolution(uint32 id) -{ - video_depth m = VDEPTH_1BIT; - vector::const_iterator i, end = VideoModes.end(); - for (i = VideoModes.begin(); i != end; ++i) { - if (i->depth > m) - m = i->depth; - } - return m; -} - - -/* - * Get X/Y size of specified resolution - */ - -static void get_size_of_resolution(uint32 id, uint32 &x, uint32 &y) -{ - vector::const_iterator i, end = VideoModes.end(); - for (i = VideoModes.begin(); i != end; ++i) { - if (i->resolution_id == id) { - x = i->x; - y = i->y; - return; - } - } - x = y = 0; -} - - -/* - * Get bytes-per-row value for specified resolution/depth - */ - -uint32 video_bytes_per_row(video_depth depth, uint32 id) -{ - vector::const_iterator i, end = VideoModes.end(); - for (i = VideoModes.begin(); i != end; ++i) { - if (i->depth == depth && i->resolution_id == id) - return i->bytes_per_row; - } - uint32 x, y; - get_size_of_resolution(id, x, y); - return TrivialBytesPerRow(x, depth); -} +// Vector of pointers to available monitor descriptions, filled by VideoInit() +vector VideoMonitors; /* @@ -198,18 +66,154 @@ static int palette_size(video_depth depth) } +/* + * Find pointer to monitor_desc for given slot ID (or NULL if not found) + */ + +static monitor_desc *find_monitor(uint8 id) +{ + vector::const_iterator i, end = VideoMonitors.end(); + for (i = VideoMonitors.begin(); i != end; ++i) { + if ((*i)->get_slot_id() == id) + return *i; + } + return NULL; +} + + +/* + * monitor_desc constructor + */ + +monitor_desc::monitor_desc(const vector &available_modes, video_depth default_depth, uint32 default_id) : modes(available_modes) +{ + // Assign the next slot ID on construction + slot_id = next_slot_id++; + + // Initialize Apple mode list + uint16 mode = 0x80; + for (int depth = VDEPTH_1BIT; depth <= VDEPTH_32BIT; depth++) { + if (has_depth(video_depth(depth))) + apple_mode_for_depth[depth] = mode++; + else + apple_mode_for_depth[depth] = 0; + } + + // Set default mode + current_mode = find_mode(depth_to_apple_mode(default_depth), default_id); +} + + +/* + * Get bytes-per-row value for specified resolution/depth + * (if the mode isn't supported, make a good guess) + */ + +uint32 monitor_desc::get_bytes_per_row(video_depth depth, uint32 id) const +{ + vector::const_iterator i, end = modes.end(); + for (i = modes.begin(); i != end; ++i) { + if (i->depth == depth && i->resolution_id == id) + return i->bytes_per_row; + } + uint32 x, y; + get_size_of_resolution(id, x, y); + return TrivialBytesPerRow(x, depth); +} + + +/* + * Check whether a mode with the specified depth exists on this display + */ + +bool monitor_desc::has_depth(video_depth depth) const +{ + vector::const_iterator i = modes.begin(), end = modes.end(); + while (i != end) { + if (i->depth == depth) + return true; + ++i; + } + return false; +} + + +/* + * Check whether the specified resolution ID is one of the supported resolutions + */ + +bool monitor_desc::has_resolution(uint32 id) const +{ + vector::const_iterator i, end = modes.end(); + for (i = modes.begin(); i != end; ++i) { + if (i->resolution_id == id) + return true; + } + return false; +} + + +/* + * Find specified mode (depth/resolution) (or invalid_mode() if not found) + */ + +vector::const_iterator monitor_desc::find_mode(uint16 apple_mode, uint32 id) const +{ + vector::const_iterator i, end = modes.end(); + for (i = modes.begin(); i != end; ++i) { + if (i->resolution_id == id && depth_to_apple_mode(i->depth) == apple_mode) + return i; + } + return i; +} + + +/* + * Find maximum supported depth for given resolution ID + */ + +video_depth monitor_desc::max_depth_of_resolution(uint32 id) const +{ + video_depth m = VDEPTH_1BIT; + vector::const_iterator i, end = modes.end(); + for (i = modes.begin(); i != end; ++i) { + if (i->depth > m) + m = i->depth; + } + return m; +} + + +/* + * Get X/Y size of specified resolution + */ + +void monitor_desc::get_size_of_resolution(uint32 id, uint32 &x, uint32 &y) const +{ + vector::const_iterator i, end = modes.end(); + for (i = modes.begin(); i != end; ++i) { + if (i->resolution_id == id) { + x = i->x; + y = i->y; + return; + } + } + x = y = 0; +} + + /* * Set palette to 50% gray */ -static void set_gray_palette(void) +void monitor_desc::set_gray_palette(void) { for (int i=0; i<256; i++) { - VidLocal.palette[i * 3 + 0] = 127; - VidLocal.palette[i * 3 + 1] = 127; - VidLocal.palette[i * 3 + 2] = 127; + palette[i * 3 + 0] = 127; + palette[i * 3 + 1] = 127; + palette[i * 3 + 2] = 127; } - video_set_palette(VidLocal.palette, 256); + set_palette(palette, 256); } @@ -217,14 +221,14 @@ static void set_gray_palette(void) * Load gamma-corrected black-to-white ramp to palette for direct-color mode */ -static void load_ramp_palette(void) +void monitor_desc::load_ramp_palette(void) { // Find tables for gamma correction uint8 *red_gamma = NULL, *green_gamma = NULL, *blue_gamma = NULL; bool have_gamma = false; int data_width = 0; - if (VidLocal.gamma_table) { - uint32 table = VidLocal.gamma_table; + if (gamma_table) { + uint32 table = gamma_table; red_gamma = Mac2HostAddr(table + gFormulaData + ReadMacInt16(table + gFormulaSize)); int chan_cnt = ReadMacInt16(table + gChanCnt); if (chan_cnt == 1) @@ -238,8 +242,8 @@ static void load_ramp_palette(void) have_gamma = true; } - int num = (VidLocal.desc->mode.depth == VDEPTH_16BIT ? 32 : 256); - uint8 *p = VidLocal.palette; + int num = (current_mode->depth == VDEPTH_16BIT ? 32 : 256); + uint8 *p = palette; for (int i=0; i VidLocal.alloc_gamma_table_size) { - if (VidLocal.gamma_table) { - r.a[0] = VidLocal.gamma_table; + if (size > alloc_gamma_table_size) { + if (gamma_table) { + r.a[0] = gamma_table; Execute68kTrap(0xa01f, &r); // DisposePtr() - VidLocal.gamma_table = 0; - VidLocal.alloc_gamma_table_size = 0; + gamma_table = 0; + alloc_gamma_table_size = 0; } r.d[0] = size; Execute68kTrap(0xa71e, &r); // NewPtrSysClear() if (r.a[0] == 0) return false; - VidLocal.gamma_table = r.a[0]; - VidLocal.alloc_gamma_table_size = size; + gamma_table = r.a[0]; + alloc_gamma_table_size = size; } return true; } @@ -286,25 +290,24 @@ static bool allocate_gamma_table(int size) * Set gamma table (0 = build linear ramp) */ -static bool set_gamma_table(uint32 user_table) +bool monitor_desc::set_gamma_table(uint32 user_table) { if (user_table == 0) { // Build linear ramp, 256 entries // Allocate new table, if necessary if (!allocate_gamma_table(SIZEOF_GammaTbl + 256)) return memFullErr; - uint32 table = VidLocal.gamma_table; // Initialize header - WriteMacInt16(table + gVersion, 0); - WriteMacInt16(table + gType, 0); - WriteMacInt16(table + gFormulaSize, 0); - WriteMacInt16(table + gChanCnt, 1); - WriteMacInt16(table + gDataCnt, 256); - WriteMacInt16(table + gDataWidth, 8); + WriteMacInt16(gamma_table + gVersion, 0); + WriteMacInt16(gamma_table + gType, 0); + WriteMacInt16(gamma_table + gFormulaSize, 0); + WriteMacInt16(gamma_table + gChanCnt, 1); + WriteMacInt16(gamma_table + gDataCnt, 256); + WriteMacInt16(gamma_table + gDataWidth, 8); // Build ramp - uint32 p = table + gFormulaData; + uint32 p = gamma_table + gFormulaData; for (int i=0; i<256; i++) WriteMacInt8(p + i, i); @@ -329,13 +332,12 @@ static bool set_gamma_table(uint32 user_table) int size = SIZEOF_GammaTbl + ReadMacInt16(user_table + gFormulaSize) + chan_cnt * data_cnt; if (!allocate_gamma_table(size)) return memFullErr; - uint32 table = VidLocal.gamma_table; // Copy table - Mac2Mac_memcpy(table, user_table, size); + Mac2Mac_memcpy(gamma_table, user_table, size); } - if (IsDirectMode(VidLocal.desc->mode)) + if (IsDirectMode(*current_mode)) load_ramp_palette(); return true; @@ -346,49 +348,49 @@ static bool set_gamma_table(uint32 user_table) * Switch video mode */ -static void switch_mode(const video_mode &mode, uint32 param, uint32 dce) +void monitor_desc::switch_mode(vector::const_iterator it, uint32 param, uint32 dce) { + const video_mode &mode = *it; + // Switch mode set_gray_palette(); - video_switch_to_mode(mode); + current_mode = it; + switch_to_current_mode(); - // Update VidLocal - VidLocal.current_mode = DepthToAppleMode(mode.depth); - VidLocal.current_id = mode.resolution_id; - - uint32 frame_base = VidLocal.desc->mac_frame_base; + // Update variables + current_apple_mode = depth_to_apple_mode(mode.depth); + current_id = mode.resolution_id; M68kRegisters r; - uint32 sp = VidLocal.slot_param; - r.a[0] = sp; + r.a[0] = slot_param; // Find functional sResource for this display - WriteMacInt8(sp + spSlot, ReadMacInt8(dce + dCtlSlot)); - WriteMacInt8(sp + spID, ReadMacInt8(dce + dCtlSlotId)); - WriteMacInt8(sp + spExtDev, 0); + WriteMacInt8(slot_param + spSlot, ReadMacInt8(dce + dCtlSlot)); + WriteMacInt8(slot_param + spID, ReadMacInt8(dce + dCtlSlotId)); + WriteMacInt8(slot_param + spExtDev, 0); r.d[0] = 0x0016; Execute68kTrap(0xa06e, &r); // SRsrcInfo() - uint32 rsrc = ReadMacInt32(sp + spPointer); + uint32 rsrc = ReadMacInt32(slot_param + spPointer); // Patch minorBase (otherwise rebooting won't work) - WriteMacInt8(sp + spID, 0x0a); // minorBase + WriteMacInt8(slot_param + spID, 0x0a); // minorBase r.d[0] = 0x0006; Execute68kTrap(0xa06e, &r); // SFindStruct() - uint32 minor_base = ReadMacInt32(sp + spPointer) - ROMBaseMac; - ROMBaseHost[minor_base + 0] = frame_base >> 24; - ROMBaseHost[minor_base + 1] = frame_base >> 16; - ROMBaseHost[minor_base + 2] = frame_base >> 8; - ROMBaseHost[minor_base + 3] = frame_base; + uint32 minor_base = ReadMacInt32(slot_param + spPointer) - ROMBaseMac; + ROMBaseHost[minor_base + 0] = mac_frame_base >> 24; + ROMBaseHost[minor_base + 1] = mac_frame_base >> 16; + ROMBaseHost[minor_base + 2] = mac_frame_base >> 8; + ROMBaseHost[minor_base + 3] = mac_frame_base; // Patch video mode parameter table - WriteMacInt32(sp + spPointer, rsrc); - WriteMacInt8(sp + spID, DepthToAppleMode(mode.depth)); + WriteMacInt32(slot_param + spPointer, rsrc); + WriteMacInt8(slot_param + spID, depth_to_apple_mode(mode.depth)); r.d[0] = 0x0006; Execute68kTrap(0xa06e, &r); // SFindStruct() - WriteMacInt8(sp + spID, 0x01); + WriteMacInt8(slot_param + spID, 0x01); r.d[0] = 0x0006; Execute68kTrap(0xa06e, &r); // SFindStruct() - uint32 p = ReadMacInt32(sp + spPointer) - ROMBaseMac; + uint32 p = ReadMacInt32(slot_param + spPointer) - ROMBaseMac; ROMBaseHost[p + 8] = mode.bytes_per_row >> 8; ROMBaseHost[p + 9] = mode.bytes_per_row; ROMBaseHost[p + 14] = mode.y >> 8; @@ -400,23 +402,24 @@ static void switch_mode(const video_mode &mode, uint32 param, uint32 dce) ChecksumSlotROM(); // Update sResource - WriteMacInt8(sp + spID, ReadMacInt8(dce + dCtlSlotId)); + WriteMacInt8(slot_param + spID, ReadMacInt8(dce + dCtlSlotId)); r.d[0] = 0x002b; Execute68kTrap(0xa06e, &r); // SUpdateSRT() // Update frame buffer base in DCE and param block - WriteMacInt32(dce + dCtlDevBase, frame_base); - WriteMacInt32(param + csBaseAddr, frame_base); + WriteMacInt32(dce + dCtlDevBase, mac_frame_base); + WriteMacInt32(param + csBaseAddr, mac_frame_base); // Patch frame buffer base address for MacOS versions <7.6 - if (!VidLocal.dm_present) { // Only do this when no Display Manager seems to be present; otherwise, the screen will not get redrawn - WriteMacInt32(0x824, frame_base); // ScrnBase - WriteMacInt32(0x898, frame_base); // CrsrBase + if (!dm_present) { // Only do this when no Display Manager seems to be present; otherwise, the screen will not get redrawn + D(bug("No Display Manager, patching frame buffer base\n")); + WriteMacInt32(0x824, mac_frame_base); // ScrnBase + WriteMacInt32(0x898, mac_frame_base); // CrsrBase uint32 gdev = ReadMacInt32(0x8a4); // MainDevice gdev = ReadMacInt32(gdev); uint32 pmap = ReadMacInt32(gdev + 0x16); // gdPMap pmap = ReadMacInt32(pmap); - WriteMacInt32(pmap, frame_base); // baseAddr + WriteMacInt32(pmap, mac_frame_base); // baseAddr } } @@ -425,23 +428,18 @@ static void switch_mode(const video_mode &mode, uint32 param, uint32 dce) * Driver Open() routine */ -int16 VideoDriverOpen(uint32 pb, uint32 dce) +int16 monitor_desc::driver_open(void) { - D(bug("VideoDriverOpen\n")); - // This shouldn't happen unless the platform-specific video code is broken - if (VideoModes.empty()) + if (modes.empty()) fprintf(stderr, "No valid video modes found (broken video driver?)\n"); // Init local variables - VidLocal.desc = &VideoMonitor; - VidLocal.luminance_mapping = false; - VidLocal.interrupts_enabled = false; - VidLocal.current_mode = DepthToAppleMode(VidLocal.desc->mode.depth); - VidLocal.current_id = VidLocal.desc->mode.resolution_id; - VidLocal.preferred_mode = VidLocal.current_mode; - VidLocal.preferred_id = VidLocal.current_id; - VidLocal.dm_present = false; + luminance_mapping = false; + interrupts_enabled = false; + current_apple_mode = preferred_apple_mode = depth_to_apple_mode(current_mode->depth); + current_id = preferred_id = current_mode->resolution_id; + dm_present = false; // Allocate Slot Manager parameter block in Mac RAM M68kRegisters r; @@ -449,12 +447,12 @@ int16 VideoDriverOpen(uint32 pb, uint32 dce) Execute68kTrap(0xa71e, &r); // NewPtrSysClear() if (r.a[0] == 0) return memFullErr; - VidLocal.slot_param = r.a[0]; - D(bug("SPBlock at %08x\n", VidLocal.slot_param)); + slot_param = r.a[0]; + D(bug("SPBlock at %08x\n", slot_param)); // Find and set default gamma table - VidLocal.gamma_table = 0; - VidLocal.alloc_gamma_table_size = 0; + gamma_table = 0; + alloc_gamma_table_size = 0; set_gamma_table(0); // Init color palette (solid gray) @@ -462,16 +460,25 @@ int16 VideoDriverOpen(uint32 pb, uint32 dce) return noErr; } +int16 VideoDriverOpen(uint32 pb, uint32 dce) +{ + uint8 slot_id = ReadMacInt8(dce + dCtlSlotId); + D(bug("VideoDriverOpen slot %02x\n", slot_id)); + + monitor_desc *m = find_monitor(slot_id); + if (m) + return m->driver_open(); + else + return nsDrvErr; +} + /* * Driver Control() routine */ -int16 VideoDriverControl(uint32 pb, uint32 dce) +int16 monitor_desc::driver_control(uint16 code, uint32 param, uint32 dce) { - uint16 code = ReadMacInt16(pb + csCode); - uint32 param = ReadMacInt32(pb + csParam); - D(bug("VideoDriverControl %d\n", code)); switch (code) { case cscSetMode: { // Set color depth @@ -479,25 +486,25 @@ int16 VideoDriverControl(uint32 pb, uint32 dce) D(bug(" SetMode %04x\n", mode)); // Set old base address in case the switch fails - WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base); + WriteMacInt32(param + csBaseAddr, mac_frame_base); if (ReadMacInt16(param + csPage)) return paramErr; - if (mode != VidLocal.current_mode) { - vector::const_iterator i = find_mode(mode, VidLocal.current_id); - if (i == VideoModes.end()) + if (mode != current_apple_mode) { + vector::const_iterator i = find_mode(mode, current_id); + if (i == invalid_mode()) return paramErr; - switch_mode(*i, param, dce); + switch_mode(i, param, dce); } - D(bug(" base %08x\n", VidLocal.desc->mac_frame_base)); + D(bug(" base %08x\n", mac_frame_base)); return noErr; } case cscSetEntries: // Set palette case cscDirectSetEntries: { D(bug(" (Direct)SetEntries table %08x, count %d, start %d\n", ReadMacInt32(param + csTable), ReadMacInt16(param + csCount), ReadMacInt16(param + csStart))); - bool is_direct = IsDirectMode(VidLocal.desc->mode); + bool is_direct = IsDirectMode(*current_mode); if (code == cscSetEntries && is_direct) return controlErr; if (code == cscDirectSetEntries && !is_direct) @@ -514,29 +521,28 @@ int16 VideoDriverControl(uint32 pb, uint32 dce) uint8 *red_gamma = NULL, *green_gamma = NULL, *blue_gamma = NULL; bool have_gamma = false; int data_width = 0; - if (VidLocal.gamma_table) { - uint32 table = VidLocal.gamma_table; - red_gamma = Mac2HostAddr(table + gFormulaData + ReadMacInt16(table + gFormulaSize)); - int chan_cnt = ReadMacInt16(table + gChanCnt); + if (gamma_table) { + red_gamma = Mac2HostAddr(gamma_table + gFormulaData + ReadMacInt16(gamma_table + gFormulaSize)); + int chan_cnt = ReadMacInt16(gamma_table + gChanCnt); if (chan_cnt == 1) green_gamma = blue_gamma = red_gamma; else { - int ofs = ReadMacInt16(table + gDataCnt); + int ofs = ReadMacInt16(gamma_table + gDataCnt); green_gamma = red_gamma + ofs; blue_gamma = green_gamma + ofs; } - data_width = ReadMacInt16(table + gDataWidth); + data_width = ReadMacInt16(gamma_table + gDataWidth); have_gamma = true; } // Convert palette if (start == 0xffff) { // Indexed for (uint32 i=0; i<=count; i++) { - d_pal = VidLocal.palette + (ReadMacInt16(s_pal) & 0xff) * 3; + d_pal = palette + (ReadMacInt16(s_pal) & 0xff) * 3; uint8 red = (uint16)ReadMacInt16(s_pal + 2) >> 8; uint8 green = (uint16)ReadMacInt16(s_pal + 4) >> 8; uint8 blue = (uint16)ReadMacInt16(s_pal + 6) >> 8; - if (VidLocal.luminance_mapping && !is_direct) + if (luminance_mapping && !is_direct) red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16; if (have_gamma) { red = red_gamma[red >> (8 - data_width)]; @@ -551,12 +557,12 @@ int16 VideoDriverControl(uint32 pb, uint32 dce) } else { // Sequential if (start + count > 255) return paramErr; - d_pal = VidLocal.palette + start * 3; + d_pal = palette + start * 3; for (uint32 i=0; i<=count; i++) { uint8 red = (uint16)ReadMacInt16(s_pal + 2) >> 8; uint8 green = (uint16)ReadMacInt16(s_pal + 4) >> 8; uint8 blue = (uint16)ReadMacInt16(s_pal + 6) >> 8; - if (VidLocal.luminance_mapping && !is_direct) + if (luminance_mapping && !is_direct) red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16; if (have_gamma) { red = red_gamma[red >> (8 - data_width)]; @@ -569,7 +575,7 @@ int16 VideoDriverControl(uint32 pb, uint32 dce) s_pal += 8; } } - video_set_palette(VidLocal.palette, palette_size(VidLocal.desc->mode.depth)); + set_palette(palette, palette_size(current_mode->depth)); return noErr; } @@ -592,20 +598,20 @@ int16 VideoDriverControl(uint32 pb, uint32 dce) 0xffff0000, // 16 bpp 0xffffffff // 32 bpp }; - uint32 frame_base = VidLocal.desc->mac_frame_base; - uint32 pat = pattern[VidLocal.desc->mode.depth]; - bool invert = (VidLocal.desc->mode.depth == VDEPTH_32BIT); - for (uint32 y=0; ymode.y; y++) { - for (uint32 x=0; xmode.bytes_per_row; x+=4) { - WriteMacInt32(frame_base + x, pat); + uint32 p = mac_frame_base; + uint32 pat = pattern[current_mode->depth]; + bool invert = (current_mode->depth == VDEPTH_32BIT); + for (uint32 y=0; yy; y++) { + for (uint32 x=0; xbytes_per_row; x+=4) { + WriteMacInt32(p + x, pat); if (invert) pat = ~pat; } - frame_base += VidLocal.desc->mode.bytes_per_row; + p += current_mode->bytes_per_row; pat = ~pat; } - if (IsDirectMode(VidLocal.desc->mode)) + if (IsDirectMode(*current_mode)) load_ramp_palette(); return noErr; @@ -613,18 +619,18 @@ int16 VideoDriverControl(uint32 pb, uint32 dce) case cscSetGray: // Enable/disable luminance mapping D(bug(" SetGray %02x\n", ReadMacInt8(param + csMode))); - VidLocal.luminance_mapping = ReadMacInt8(param + csMode); + luminance_mapping = ReadMacInt8(param + csMode); return noErr; case cscSetInterrupt: // Enable/disable VBL D(bug(" SetInterrupt %02x\n", ReadMacInt8(param + csMode))); - VidLocal.interrupts_enabled = (ReadMacInt8(param + csMode) == 0); + interrupts_enabled = (ReadMacInt8(param + csMode) == 0); return noErr; case cscSetDefaultMode: { // Set default color depth uint16 mode = ReadMacInt8(param + csMode); D(bug(" SetDefaultMode %02x\n", mode)); - VidLocal.preferred_mode = mode; + preferred_apple_mode = mode; return noErr; } @@ -634,18 +640,18 @@ int16 VideoDriverControl(uint32 pb, uint32 dce) D(bug(" SwitchMode %04x, %08x\n", mode, id)); // Set old base address in case the switch fails - WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base); + WriteMacInt32(param + csBaseAddr, mac_frame_base); if (ReadMacInt16(param + csPage)) return paramErr; - if (mode != VidLocal.current_mode || id != VidLocal.current_id) { + if (mode != current_apple_mode || id != current_id) { vector::const_iterator i = find_mode(mode, id); - if (i == VideoModes.end()) + if (i == invalid_mode()) return paramErr; - switch_mode(*i, param, dce); + switch_mode(i, param, dce); } - D(bug(" base %08x\n", VidLocal.desc->mac_frame_base)); + D(bug(" base %08x\n", mac_frame_base)); return noErr; } @@ -653,8 +659,8 @@ int16 VideoDriverControl(uint32 pb, uint32 dce) uint16 mode = ReadMacInt16(param + csMode); uint32 id = ReadMacInt32(param + csData); D(bug(" SavePreferredConfiguration %04x, %08x\n", mode, id)); - VidLocal.preferred_mode = mode; - VidLocal.preferred_id = id; + preferred_apple_mode = mode; + preferred_id = id; return noErr; } @@ -664,23 +670,34 @@ int16 VideoDriverControl(uint32 pb, uint32 dce) } } +int16 VideoDriverControl(uint32 pb, uint32 dce) +{ + uint8 slot_id = ReadMacInt8(dce + dCtlSlotId); + uint16 code = ReadMacInt16(pb + csCode); + uint32 param = ReadMacInt32(pb + csParam); + D(bug("VideoDriverControl slot %02x, code %d\n", slot_id, code)); + + monitor_desc *m = find_monitor(slot_id); + if (m) + return m->driver_control(code, param, dce); + else + return nsDrvErr; +} + /* * Driver Status() routine */ -int16 VideoDriverStatus(uint32 pb, uint32 dce) +int16 monitor_desc::driver_status(uint16 code, uint32 param) { - uint16 code = ReadMacInt16(pb + csCode); - uint32 param = ReadMacInt32(pb + csParam); - D(bug("VideoDriverStatus %d\n", code)); switch (code) { case cscGetMode: // Get current color depth - D(bug(" GetMode -> %04x, base %08x\n", VidLocal.current_mode, VidLocal.desc->mac_frame_base)); - WriteMacInt16(param + csMode, VidLocal.current_mode); + D(bug(" GetMode -> %04x, base %08x\n", current_apple_mode, mac_frame_base)); + WriteMacInt16(param + csMode, current_apple_mode); WriteMacInt16(param + csPage, 0); - WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base); + WriteMacInt32(param + csBaseAddr, mac_frame_base); return noErr; case cscGetEntries: { // Read palette @@ -695,7 +712,7 @@ int16 VideoDriverStatus(uint32 pb, uint32 dce) if (start == 0xffff) { // Indexed for (uint32 i=0; i<=count; i++) { - s_pal = VidLocal.palette + (ReadMacInt16(d_pal) & 0xff) * 3; + s_pal = palette + (ReadMacInt16(d_pal) & 0xff) * 3; uint8 red = *s_pal++; uint8 green = *s_pal++; uint8 blue = *s_pal++; @@ -707,7 +724,7 @@ int16 VideoDriverStatus(uint32 pb, uint32 dce) } else { // Sequential if (start + count > 255) return paramErr; - s_pal = VidLocal.palette + start * 3; + s_pal = palette + start * 3; for (uint32 i=0; i<=count; i++) { uint8 red = *s_pal++; uint8 green = *s_pal++; @@ -727,39 +744,39 @@ int16 VideoDriverStatus(uint32 pb, uint32 dce) return noErr; case cscGetBaseAddress: // Get page base address - D(bug(" GetBaseAddress -> %08x\n", VidLocal.desc->mac_frame_base)); - WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base); + D(bug(" GetBaseAddress -> %08x\n", mac_frame_base)); + WriteMacInt32(param + csBaseAddr, mac_frame_base); if (ReadMacInt16(param + csPage)) return paramErr; else return noErr; case cscGetGray: // Get luminance mapping flag - D(bug(" GetGray -> %d\n", VidLocal.luminance_mapping)); - WriteMacInt8(param, VidLocal.luminance_mapping ? 1 : 0); + D(bug(" GetGray -> %d\n", luminance_mapping)); + WriteMacInt8(param, luminance_mapping ? 1 : 0); return noErr; case cscGetInterrupt: // Get interrupt disable flag - D(bug(" GetInterrupt -> %d\n", VidLocal.interrupts_enabled)); - WriteMacInt8(param, VidLocal.interrupts_enabled ? 0 : 1); + D(bug(" GetInterrupt -> %d\n", interrupts_enabled)); + WriteMacInt8(param, interrupts_enabled ? 0 : 1); return noErr; case cscGetGamma: - D(bug(" GetGamma -> %08x\n", VidLocal.gamma_table)); - WriteMacInt32(param + csGTable, VidLocal.gamma_table); + D(bug(" GetGamma -> %08x\n", gamma_table)); + WriteMacInt32(param + csGTable, gamma_table); return noErr; case cscGetDefaultMode: // Get default color depth - D(bug(" GetDefaultMode -> %02x\n", VidLocal.preferred_mode)); - WriteMacInt8(param + csMode, VidLocal.preferred_mode); + D(bug(" GetDefaultMode -> %02x\n", preferred_apple_mode)); + WriteMacInt8(param + csMode, preferred_apple_mode); return noErr; case cscGetCurrentMode: // Get current video mode (depth and resolution) - D(bug(" GetCurMode -> %04x/%08x, base %08x\n", VidLocal.current_mode, VidLocal.current_id, VidLocal.desc->mac_frame_base)); - WriteMacInt16(param + csMode, VidLocal.current_mode); - WriteMacInt32(param + csData, VidLocal.current_id); + D(bug(" GetCurMode -> %04x/%08x, base %08x\n", current_apple_mode, current_id, mac_frame_base)); + WriteMacInt16(param + csMode, current_apple_mode); + WriteMacInt32(param + csData, current_id); WriteMacInt16(param + csPage, 0); - WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base); + WriteMacInt32(param + csBaseAddr, mac_frame_base); return noErr; case cscGetConnection: // Get monitor information @@ -780,21 +797,21 @@ int16 VideoDriverStatus(uint32 pb, uint32 dce) WriteMacInt32(param + csTimingFormat, FOURCC('d', 'e', 'c', 'l')); WriteMacInt32(param + csTimingData, 0); // unknown uint32 flags = 0xb; // mode valid, safe and shown in Monitors panel - if (id == VidLocal.preferred_id) + if (id == preferred_id) flags |= 4; // default mode WriteMacInt32(param + csTimingFlags, flags); return noErr; } case cscGetModeBaseAddress: // Get frame buffer base address - D(bug(" GetModeBaseAddress -> base %08x\n", VidLocal.desc->mac_frame_base)); - WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base); + D(bug(" GetModeBaseAddress -> base %08x\n", mac_frame_base)); + WriteMacInt32(param + csBaseAddr, mac_frame_base); return noErr; case cscGetPreferredConfiguration: // Get default video mode (depth and resolution) - D(bug(" GetPreferredConfiguration -> %04x/%08x\n", VidLocal.preferred_mode, VidLocal.preferred_id)); - WriteMacInt16(param + csMode, VidLocal.preferred_mode); - WriteMacInt32(param + csData, VidLocal.preferred_id); + D(bug(" GetPreferredConfiguration -> %04x/%08x\n", preferred_apple_mode, preferred_id)); + WriteMacInt16(param + csMode, preferred_apple_mode); + WriteMacInt32(param + csData, preferred_id); return noErr; case cscGetNextResolution: { // Called iteratively to obtain a list of all supported resolutions @@ -804,7 +821,7 @@ int16 VideoDriverStatus(uint32 pb, uint32 dce) switch (id) { case 0: // Return current resolution - id = VidLocal.current_id; + id = current_id; break; case 0xfffffffe: @@ -834,7 +851,7 @@ int16 VideoDriverStatus(uint32 pb, uint32 dce) WriteMacInt32(param + csHorizontalPixels, x); WriteMacInt32(param + csVerticalLines, y); WriteMacInt32(param + csRefreshRate, 75 << 16); - WriteMacInt16(param + csMaxDepthMode, DepthToAppleMode(max_depth_of_resolution(id))); + WriteMacInt16(param + csMaxDepthMode, depth_to_apple_mode(max_depth_of_resolution(id))); WriteMacInt32(param + csResolutionFlags, 0); return noErr; } @@ -843,11 +860,12 @@ int16 VideoDriverStatus(uint32 pb, uint32 dce) uint32 id = ReadMacInt32(param + csDisplayModeID); uint16 mode = ReadMacInt16(param + csDepthMode); D(bug(" GetVideoParameters %04x/%08x\n", mode, id)); - VidLocal.dm_present = true; // Display Manager seems to be present + dm_present = true; // Display Manager seems to be present + D(bug(" Display Manager detected\n")); - vector::const_iterator i, end = VideoModes.end(); - for (i = VideoModes.begin(); i != end; ++i) { - if (DepthToAppleMode(i->depth) == mode && i->resolution_id == id) { + vector::const_iterator i, end = modes.end(); + for (i = modes.begin(); i != end; ++i) { + if (depth_to_apple_mode(i->depth) == mode && i->resolution_id == id) { uint32 vp = ReadMacInt32(param + csVPBlockPtr); WriteMacInt32(vp + vpBaseOffset, 0); WriteMacInt16(vp + vpRowBytes, i->bytes_per_row); @@ -912,3 +930,17 @@ int16 VideoDriverStatus(uint32 pb, uint32 dce) return statusErr; } } + +int16 VideoDriverStatus(uint32 pb, uint32 dce) +{ + uint8 slot_id = ReadMacInt8(dce + dCtlSlotId); + uint16 code = ReadMacInt16(pb + csCode); + uint32 param = ReadMacInt32(pb + csParam); + D(bug("VideoDriverStatus slot %02x, code %d\n", slot_id, code)); + + monitor_desc *m = find_monitor(slot_id); + if (m) + return m->driver_status(code, param); + else + return nsDrvErr; +}