1
0
mirror of https://github.com/kanjitalk755/macemu.git synced 2025-03-05 03:29:35 +00:00

- 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
This commit is contained in:
cebix 2002-04-25 11:00:31 +00:00
parent 665c64b4aa
commit 8871da753d
6 changed files with 676 additions and 505 deletions

@ -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;

@ -39,10 +39,6 @@
#include <algorithm>
#ifndef NO_STD_NAMESPACE
using std::sort;
#endif
#ifdef HAVE_PTHREADS
# include <pthread.h>
#endif
@ -71,6 +67,9 @@ using std::sort;
#include "debug.h"
// Supported video modes
static vector<video_mode> 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<video_mode> &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<video_mode *>(&mode)->bytes_per_row = bytes_per_row;
const_cast<video_mode *>(&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<video_mode *>(&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; i<num; i++) {
int c = (i * 256) / num;
palette[i].pixel = map_rgb(c, c, c);
palette[i].flags = DoRed | DoGreen | DoBlue;
x_palette[i].pixel = map_rgb(c, c, c);
x_palette[i].flags = DoRed | DoGreen | DoBlue;
}
} else if (color_class == PseudoColor) {
for (int i=0; i<256; i++) {
palette[i].pixel = i;
palette[i].flags = DoRed | DoGreen | DoBlue;
x_palette[i].pixel = i;
x_palette[i].flags = DoRed | DoGreen | DoBlue;
}
}
@ -1389,13 +1407,13 @@ static bool video_open(const video_mode &mode)
int num = (color_class == DirectColor ? vis->map_entries : 256);
for (int i=0; i<num; i++) {
int c = (i * 256) / num;
palette[i].red = c * 0x0101;
palette[i].green = c * 0x0101;
palette[i].blue = c * 0x0101;
x_palette[i].red = c * 0x0101;
x_palette[i].green = c * 0x0101;
x_palette[i].blue = c * 0x0101;
}
if (color_class == PseudoColor || color_class == DirectColor) {
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);
}
#ifdef ENABLE_VOSF
@ -1408,16 +1426,16 @@ static bool video_open(const video_mode &mode)
// Create display driver object of requested type
switch (display_type) {
case DISPLAY_WINDOW:
drv = new driver_window(mode);
drv = new driver_window(*this);
break;
#ifdef ENABLE_FBDEV_DGA
case DISPLAY_DGA:
drv = new driver_fbdev(mode);
drv = new driver_fbdev(*this);
break;
#endif
#ifdef ENABLE_XF86_DGA
case DISPLAY_DGA:
drv = new driver_xf86dga(mode);
drv = new driver_xf86dga(*this);
break;
#endif
}
@ -1432,7 +1450,7 @@ static bool video_open(const video_mode &mode)
#ifdef ENABLE_VOSF
if (use_vosf) {
// Initialize the VOSF system
if (!video_vosf_init()) {
if (!video_vosf_init(*this)) {
ErrorAlert(STR_VOSF_INIT_ERR);
return false;
}
@ -1494,7 +1512,7 @@ bool VideoInit(bool classic)
ErrorAlert(STR_UNSUPP_DEPTH_ERR);
return false;
}
sort(avail_depths, avail_depths + num_depths);
std::sort(avail_depths, avail_depths + num_depths);
#ifdef ENABLE_FBDEV_DGA
// Frame buffer name
@ -1597,34 +1615,39 @@ bool VideoInit(bool classic)
ErrorAlert(STR_NO_XVISUAL_ERR);
return false;
}
video_init_depth_list();
// Find requested default mode with specified dimensions
uint32 default_id;
std::vector<video_mode>::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<video_mode>::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<video_mode>::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<monitor_desc *>::iterator i, end = VideoMonitors.end();
for (i = VideoMonitors.begin(); i != end; ++i)
dynamic_cast<X11_monitor_desc *>(*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; i<num_out; i++) {
int c = (stretch ? (i * num_in) / num_out : i);
p->red = 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<VideoMonitor.mode.y; j++) {
for (j=0; j<mode.y; j++) {
if (memcmp(&the_buffer[j * bytes_per_row], &the_buffer_copy[j * bytes_per_row], bytes_per_row)) {
y1 = j;
break;
}
}
y2 = y1 - 1;
for (j=VideoMonitor.mode.y-1; 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();
}

@ -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<video_mode> 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<video_mode> &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<video_mode> modes; // List of supported video modes
vector<video_mode>::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<video_mode>::const_iterator invalid_mode(void) const {return modes.end();}
// Find specified mode (depth/resolution) (or invalid_mode() if not found)
vector<video_mode>::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<video_mode>::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<monitor_desc *> 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

@ -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

@ -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<monitor_desc *>::const_iterator m, mend = VideoMonitors.end();
vector<uint32> 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();

@ -41,143 +41,11 @@
#include "debug.h"
// List of supported video modes
vector<video_mode> 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<video_mode>::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<video_mode>::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<video_mode>::const_iterator find_mode(uint16 mode, uint32 id)
{
vector<video_mode>::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<video_mode>::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<video_mode>::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<video_mode>::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<monitor_desc *> 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<monitor_desc *>::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<video_mode> &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<video_mode>::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<video_mode>::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<video_mode>::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<video_mode>::const_iterator monitor_desc::find_mode(uint16 apple_mode, uint32 id) const
{
vector<video_mode>::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<video_mode>::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<video_mode>::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<num; i++) {
uint8 red = (i * 256 / num), green = red, blue = red;
if (have_gamma) {
@ -252,7 +256,7 @@ static void load_ramp_palette(void)
*p++ = blue;
}
video_set_palette(VidLocal.palette, num);
set_palette(palette, num);
}
@ -260,23 +264,23 @@ static void load_ramp_palette(void)
* Allocate gamma table of specified size
*/
static bool allocate_gamma_table(int size)
bool monitor_desc::allocate_gamma_table(int size)
{
M68kRegisters r;
if (size > 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<video_mode>::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<video_mode>::const_iterator i = find_mode(mode, VidLocal.current_id);
if (i == VideoModes.end())
if (mode != current_apple_mode) {
vector<video_mode>::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; y<VidLocal.desc->mode.y; y++) {
for (uint32 x=0; x<VidLocal.desc->mode.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; y<current_mode->y; y++) {
for (uint32 x=0; x<current_mode->bytes_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<video_mode>::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<video_mode>::const_iterator i, end = VideoModes.end();
for (i = VideoModes.begin(); i != end; ++i) {
if (DepthToAppleMode(i->depth) == mode && i->resolution_id == id) {
vector<video_mode>::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;
}