/* * video_beos.cpp - Video/graphics emulation, BeOS specific things * * SheepShaver (C) 1997-2002 Marc Hellwig and Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "sysdeps.h" #include "video.h" #include "video_defs.h" #include "main.h" #include "adb.h" #include "prefs.h" #include "user_strings.h" #include "about_window.h" #include "version.h" #define DEBUG 0 #include "debug.h" // Global variables static sem_id video_lock = -1; // Protection during mode changes static sem_id mac_os_lock = -1; // This is used to stop the MacOS thread when the SheepShaver workspace is switched out // Prototypes static filter_result filter_func(BMessage *msg, BHandler **target, BMessageFilter *filter); // From sys_beos.cpp extern void SysCreateVolumeMenu(BMenu *menu, uint32 msg); extern void SysMountVolume(const char *name); #include "video_window.h" #include "video_screen.h" /* * Display manager thread (for opening and closing windows and screens; * this is not safe under R4 when running on the MacOS stack in kernel * space) */ // Message constants const uint32 MSG_OPEN_WINDOW = 'owin'; const uint32 MSG_CLOSE_WINDOW = 'cwin'; const uint32 MSG_OPEN_SCREEN = 'oscr'; const uint32 MSG_CLOSE_SCREEN = 'cscr'; const uint32 MSG_QUIT_DISPLAY_MANAGER = 'quit'; static thread_id dm_thread = -1; static sem_id dm_done_sem = -1; static status_t display_manager(void *arg) { for (;;) { // Receive message thread_id sender; uint32 code = receive_data(&sender, NULL, 0); D(bug("Display manager received %08lx\n", code)); switch (code) { case MSG_QUIT_DISPLAY_MANAGER: return 0; case MSG_OPEN_WINDOW: D(bug("Opening window\n")); the_window = new MacWindow(BRect(0, 0, VModes[cur_mode].viXsize-1, VModes[cur_mode].viYsize-1)); D(bug("Opened\n")); break; case MSG_CLOSE_WINDOW: if (the_window != NULL) { D(bug("Posting quit to window\n")); the_window->PostMessage(B_QUIT_REQUESTED); D(bug("Posted, waiting\n")); while (the_window) snooze(200000); D(bug("Window closed\n")); } break; case MSG_OPEN_SCREEN: { D(bug("Opening screen\n")); long scr_mode = 0; switch (VModes[cur_mode].viAppleMode) { case APPLE_8_BIT: switch (VModes[cur_mode].viAppleID) { case APPLE_640x480: scr_mode = B_8_BIT_640x480; break; case APPLE_800x600: scr_mode = B_8_BIT_800x600; break; case APPLE_1024x768: scr_mode = B_8_BIT_1024x768; break; case APPLE_1152x900: scr_mode = B_8_BIT_1152x900; break; case APPLE_1280x1024: scr_mode = B_8_BIT_1280x1024; break; case APPLE_1600x1200: scr_mode = B_8_BIT_1600x1200; break; } break; case APPLE_16_BIT: switch (VModes[cur_mode].viAppleID) { case APPLE_640x480: scr_mode = B_15_BIT_640x480; break; case APPLE_800x600: scr_mode = B_15_BIT_800x600; break; case APPLE_1024x768: scr_mode = B_15_BIT_1024x768; break; case APPLE_1152x900: scr_mode = B_15_BIT_1152x900; break; case APPLE_1280x1024: scr_mode = B_15_BIT_1280x1024; break; case APPLE_1600x1200: scr_mode = B_15_BIT_1600x1200; break; } break; case APPLE_32_BIT: switch (VModes[cur_mode].viAppleID) { case APPLE_640x480: scr_mode = B_32_BIT_640x480; break; case APPLE_800x600: scr_mode = B_32_BIT_800x600; break; case APPLE_1024x768: scr_mode = B_32_BIT_1024x768; break; case APPLE_1152x900: scr_mode = B_32_BIT_1152x900; break; case APPLE_1280x1024: scr_mode = B_32_BIT_1280x1024; break; case APPLE_1600x1200: scr_mode = B_32_BIT_1600x1200; break; } break; } the_screen = new MacScreen(GetString(STR_WINDOW_TITLE), scr_mode); D(bug("Opened, error %08lx\n", screen_error)); if (screen_error != B_NO_ERROR) { D(bug("Error, posting quit to screen\n")); the_screen->PostMessage(B_QUIT_REQUESTED); D(bug("Posted, waiting\n")); while (the_screen) snooze(200000); D(bug("Screen closed\n")); break; } // Wait for video mem access D(bug("Showing screen\n")); the_screen->Show(); D(bug("Shown, waiting for frame buffer access\n")); while (!drawing_enable) snooze(200000); D(bug("Access granted\n")); break; } case MSG_CLOSE_SCREEN: if (the_screen != NULL) { D(bug("Posting quit to screen\n")); the_screen->PostMessage(B_QUIT_REQUESTED); D(bug("Posted, waiting\n")); while (the_screen) snooze(200000); D(bug("Screen closed\n")); } break; } // Acknowledge release_sem(dm_done_sem); } } /* * Open display (window or screen) */ static void open_display(void) { D(bug("entering open_display()\n")); display_type = VModes[cur_mode].viType; if (display_type == DIS_SCREEN) { while (send_data(dm_thread, MSG_OPEN_SCREEN, NULL, 0) == B_INTERRUPTED) ; while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ; } else if (display_type == DIS_WINDOW) { while (send_data(dm_thread, MSG_OPEN_WINDOW, NULL, 0) == B_INTERRUPTED) ; while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ; } D(bug("exiting open_display()\n")); } /* * Close display */ static void close_display(void) { D(bug("entering close_display()\n")); if (display_type == DIS_SCREEN) { while (send_data(dm_thread, MSG_CLOSE_SCREEN, NULL, 0) == B_INTERRUPTED) ; while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ; } else if (display_type == DIS_WINDOW) { while (send_data(dm_thread, MSG_CLOSE_WINDOW, NULL, 0) == B_INTERRUPTED) ; while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ; } D(bug("exiting close_display()\n")); } /* * Initialization */ static void add_mode(VideoInfo *&p, uint32 allow, uint32 test, long apple_mode, long apple_id, int type) { if (allow & test) { p->viType = type; switch (apple_id) { case APPLE_W_640x480: case APPLE_640x480: p->viXsize = 640; p->viYsize = 480; break; case APPLE_W_800x600: case APPLE_800x600: p->viXsize = 800; p->viYsize = 600; break; case APPLE_1024x768: p->viXsize = 1024; p->viYsize = 768; break; case APPLE_1152x900: p->viXsize = 1152; p->viYsize = 900; break; case APPLE_1280x1024: p->viXsize = 1280; p->viYsize = 1024; break; case APPLE_1600x1200: p->viXsize = 1600; p->viYsize = 1200; break; } switch (apple_mode) { case APPLE_8_BIT: p->viRowBytes = p->viXsize; break; case APPLE_16_BIT: p->viRowBytes = p->viXsize * 2; break; case APPLE_32_BIT: p->viRowBytes = p->viXsize * 4; break; } p->viAppleMode = apple_mode; p->viAppleID = apple_id; p++; } } bool VideoInit(void) { // Init variables, create semaphores private_data = NULL; cur_mode = 0; // Window 640x480 video_lock = create_sem(1, "Video Lock"); mac_os_lock = create_sem(0, "MacOS Frame Buffer Lock"); dm_done_sem = create_sem(0, "Display Manager Done"); // Construct video mode table VideoInfo *p = VModes; uint32 window_modes = PrefsFindInt32("windowmodes"); uint32 screen_modes = PrefsFindInt32("screenmodes"); if (window_modes == 0 && screen_modes == 0) window_modes |= B_8_BIT_640x480 | B_8_BIT_800x600; // Allow at least 640x480 and 800x600 window modes add_mode(p, window_modes, B_8_BIT_640x480, APPLE_8_BIT, APPLE_W_640x480, DIS_WINDOW); add_mode(p, window_modes, B_8_BIT_800x600, APPLE_8_BIT, APPLE_W_800x600, DIS_WINDOW); add_mode(p, window_modes, B_15_BIT_640x480, APPLE_16_BIT, APPLE_W_640x480, DIS_WINDOW); add_mode(p, window_modes, B_15_BIT_800x600, APPLE_16_BIT, APPLE_W_800x600, DIS_WINDOW); add_mode(p, window_modes, B_32_BIT_640x480, APPLE_32_BIT, APPLE_W_640x480, DIS_WINDOW); add_mode(p, window_modes, B_32_BIT_800x600, APPLE_32_BIT, APPLE_W_800x600, DIS_WINDOW); add_mode(p, screen_modes, B_8_BIT_640x480, APPLE_8_BIT, APPLE_640x480, DIS_SCREEN); add_mode(p, screen_modes, B_8_BIT_800x600, APPLE_8_BIT, APPLE_800x600, DIS_SCREEN); add_mode(p, screen_modes, B_8_BIT_1024x768, APPLE_8_BIT, APPLE_1024x768, DIS_SCREEN); add_mode(p, screen_modes, B_8_BIT_1152x900, APPLE_8_BIT, APPLE_1152x900, DIS_SCREEN); add_mode(p, screen_modes, B_8_BIT_1280x1024, APPLE_8_BIT, APPLE_1280x1024, DIS_SCREEN); add_mode(p, screen_modes, B_8_BIT_1600x1200, APPLE_8_BIT, APPLE_1600x1200, DIS_SCREEN); add_mode(p, screen_modes, B_15_BIT_640x480, APPLE_16_BIT, APPLE_640x480, DIS_SCREEN); add_mode(p, screen_modes, B_15_BIT_800x600, APPLE_16_BIT, APPLE_800x600, DIS_SCREEN); add_mode(p, screen_modes, B_15_BIT_1024x768, APPLE_16_BIT, APPLE_1024x768, DIS_SCREEN); add_mode(p, screen_modes, B_15_BIT_1152x900, APPLE_16_BIT, APPLE_1152x900, DIS_SCREEN); add_mode(p, screen_modes, B_15_BIT_1280x1024, APPLE_16_BIT, APPLE_1280x1024, DIS_SCREEN); add_mode(p, screen_modes, B_15_BIT_1600x1200, APPLE_16_BIT, APPLE_1600x1200, DIS_SCREEN); add_mode(p, screen_modes, B_32_BIT_640x480, APPLE_32_BIT, APPLE_640x480, DIS_SCREEN); add_mode(p, screen_modes, B_32_BIT_800x600, APPLE_32_BIT, APPLE_800x600, DIS_SCREEN); add_mode(p, screen_modes, B_32_BIT_1024x768, APPLE_32_BIT, APPLE_1024x768, DIS_SCREEN); add_mode(p, screen_modes, B_32_BIT_1152x900, APPLE_32_BIT, APPLE_1152x900, DIS_SCREEN); add_mode(p, screen_modes, B_32_BIT_1280x1024, APPLE_32_BIT, APPLE_1280x1024, DIS_SCREEN); add_mode(p, screen_modes, B_32_BIT_1600x1200, APPLE_32_BIT, APPLE_1600x1200, DIS_SCREEN); p->viType = DIS_INVALID; // End marker p->viRowBytes = 0; p->viXsize = p->viYsize = 0; p->viAppleMode = 0; p->viAppleID = 0; // Start display manager thread dm_thread = spawn_thread(display_manager, "Display Manager", B_NORMAL_PRIORITY, NULL); resume_thread(dm_thread); // Open window/screen open_display(); if (display_type == DIS_SCREEN && the_screen == NULL) { char str[256]; sprintf(str, GetString(STR_FULL_SCREEN_ERR), strerror(screen_error), screen_error); ErrorAlert(str); return false; } return true; } /* * Deinitialization */ void VideoExit(void) { if (dm_thread >= 0) { // Close display acquire_sem(video_lock); close_display(); if (private_data != NULL) { delete private_data->gammaTable; delete private_data; } // Stop display manager status_t l; send_data(dm_thread, MSG_QUIT_DISPLAY_MANAGER, NULL, 0); while (wait_for_thread(dm_thread, &l) == B_INTERRUPTED) ; } // Delete semaphores delete_sem(video_lock); delete_sem(mac_os_lock); delete_sem(dm_done_sem); } /* * Close screen in full-screen mode */ void VideoQuitFullScreen(void) { D(bug("VideoQuitFullScreen()\n")); if (display_type == DIS_SCREEN) { acquire_sem(video_lock); close_display(); release_sem(video_lock); } } /* * Execute video VBL routine */ void VideoVBL(void) { release_sem(mac_os_lock); if (private_data != NULL && private_data->interruptsEnabled) VSLDoInterruptService(private_data->vslServiceID); while (acquire_sem(mac_os_lock) == B_INTERRUPTED) ; } /* * Filter function for receiving mouse and keyboard events */ #define MENU_IS_POWER 0 // Be -> Mac raw keycode translation table static const uint8 keycode2mac[0x80] = { 0xff, 0x35, 0x7a, 0x78, 0x63, 0x76, 0x60, 0x61, // inv Esc F1 F2 F3 F4 F5 F6 0x62, 0x64, 0x65, 0x6d, 0x67, 0x6f, 0x69, 0x6b, // F7 F8 F9 F10 F11 F12 F13 F14 0x71, 0x0a, 0x12, 0x13, 0x14, 0x15, 0x17, 0x16, // F15 ` 1 2 3 4 5 6 0x1a, 0x1c, 0x19, 0x1d, 0x1b, 0x18, 0x33, 0x72, // 7 8 9 0 - = BSP INS 0x73, 0x74, 0x47, 0x4b, 0x43, 0x4e, 0x30, 0x0c, // HOM PUP NUM / * - TAB Q 0x0d, 0x0e, 0x0f, 0x11, 0x10, 0x20, 0x22, 0x1f, // W E R T Y U I O 0x23, 0x21, 0x1e, 0x2a, 0x75, 0x77, 0x79, 0x59, // P [ ] \ DEL END PDN 7 0x5b, 0x5c, 0x45, 0x39, 0x00, 0x01, 0x02, 0x03, // 8 9 + CAP A S D F 0x05, 0x04, 0x26, 0x28, 0x25, 0x29, 0x27, 0x24, // G H J K L ; ' RET 0x56, 0x57, 0x58, 0x38, 0x06, 0x07, 0x08, 0x09, // 4 5 6 SHL Z X C V 0x0b, 0x2d, 0x2e, 0x2b, 0x2f, 0x2c, 0x38, 0x3e, // B N M , . / SHR CUP 0x53, 0x54, 0x55, 0x4c, 0x36, 0x37, 0x31, 0x37, // 1 2 3 ENT CTL ALT SPC ALT 0x36, 0x3b, 0x3d, 0x3c, 0x52, 0x41, 0x3a, 0x3a, // CTR CLF CDN CRT 0 . CMD CMD #if MENU_IS_POWER 0x7f, 0x32, 0x51, 0x7f, 0xff, 0xff, 0xff, 0xff, // MNU EUR = POW inv inv inv inv #else 0x32, 0x32, 0x51, 0x7f, 0xff, 0xff, 0xff, 0xff, // MNU EUR = POW inv inv inv inv #endif 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // inv inv inv inv inv inv inv inv }; static const uint8 modifier2mac[0x20] = { #if MENU_IS_POWER 0x38, 0x37, 0x36, 0x39, 0x6b, 0x47, 0x3a, 0x7f, // SHF CMD inv CAP F14 NUM OPT MNU #else 0x38, 0x37, 0x36, 0x39, 0x6b, 0x47, 0x3a, 0x32, // SHF CMD CTR CAP F14 NUM OPT MNU #endif 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // inv inv inv inv inv inv inv inv }; static filter_result filter_func(BMessage *msg, BHandler **target, BMessageFilter *filter) { // msg->PrintToStream(); switch (msg->what) { case B_KEY_DOWN: case B_KEY_UP: { uint32 be_code = msg->FindInt32("key") & 0xff; uint32 mac_code = keycode2mac[be_code]; // Intercept Ctrl-F1 (mount floppy disk shortcut) uint32 mods = msg->FindInt32("modifiers"); if (be_code == 0x02 && (mods & B_CONTROL_KEY)) SysMountVolume("/dev/disk/floppy/raw"); if (mac_code == 0xff) return B_DISPATCH_MESSAGE; if (msg->what == B_KEY_DOWN) ADBKeyDown(mac_code); else ADBKeyUp(mac_code); return B_SKIP_MESSAGE; } case B_MODIFIERS_CHANGED: { uint32 mods = msg->FindInt32("modifiers"); uint32 old_mods = msg->FindInt32("be:old_modifiers"); uint32 changed = mods ^ old_mods; uint32 mask = 1; for (int i=0; i<32; i++, mask<<=1) if (changed & mask) { uint32 mac_code = modifier2mac[i]; if (mac_code == 0xff) continue; if (mods & mask) ADBKeyDown(mac_code); else ADBKeyUp(mac_code); } return B_SKIP_MESSAGE; } case B_MOUSE_MOVED: { BPoint point; msg->FindPoint("where", &point); ADBMouseMoved(int(point.x), int(point.y)); return B_DISPATCH_MESSAGE; // Otherwise BitmapView::MouseMoved() wouldn't be called } case B_MOUSE_DOWN: { uint32 buttons = msg->FindInt32("buttons"); if (buttons & B_PRIMARY_MOUSE_BUTTON) ADBMouseDown(0); if (buttons & B_SECONDARY_MOUSE_BUTTON) ADBMouseDown(1); if (buttons & B_TERTIARY_MOUSE_BUTTON) ADBMouseDown(2); return B_SKIP_MESSAGE; } case B_MOUSE_UP: // B_MOUSE_UP means "all buttons released" ADBMouseUp(0); ADBMouseUp(1); ADBMouseUp(2); return B_SKIP_MESSAGE; default: return B_DISPATCH_MESSAGE; } } /* * Install graphics acceleration */ // Rectangle blitting static void accl_bitblt(accl_params *p) { D(bug("accl_bitblt\n")); // Get blitting parameters int16 src_X = p->src_rect[1] - p->src_bounds[1]; int16 src_Y = p->src_rect[0] - p->src_bounds[0]; int16 dest_X = p->dest_rect[1] - p->dest_bounds[1]; int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0]; int16 width = p->dest_rect[3] - p->dest_rect[1] - 1; int16 height = p->dest_rect[2] - p->dest_rect[0] - 1; D(bug(" src X %d, src Y %d, dest X %d, dest Y %d\n", src_X, src_Y, dest_X, dest_Y)); D(bug(" width %d, height %d\n", width, height)); // And perform the blit bitblt_hook(src_X, src_Y, dest_X, dest_Y, width, height); } static bool accl_bitblt_hook(accl_params *p) { D(bug("accl_draw_hook %p\n", p)); // Check if we can accelerate this bitblt if (p->src_base_addr == screen_base && p->dest_base_addr == screen_base && display_type == DIS_SCREEN && bitblt_hook != NULL && ((uint32 *)p)[0x18 >> 2] + ((uint32 *)p)[0x128 >> 2] == 0 && ((uint32 *)p)[0x130 >> 2] == 0 && p->transfer_mode == 0 && p->src_row_bytes > 0 && ((uint32 *)p)[0x15c >> 2] > 0) { // Yes, set function pointer p->draw_proc = accl_bitblt; return true; } return false; } // Rectangle filling/inversion static void accl_fillrect8(accl_params *p) { D(bug("accl_fillrect8\n")); // Get filling parameters int16 dest_X = p->dest_rect[1] - p->dest_bounds[1]; int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0]; int16 dest_X_max = p->dest_rect[3] - p->dest_bounds[1] - 1; int16 dest_Y_max = p->dest_rect[2] - p->dest_bounds[0] - 1; uint8 color = p->pen_mode == 8 ? p->fore_pen : p->back_pen; D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); D(bug(" dest X max %d, dest Y max %d\n", dest_X_max, dest_Y_max)); // And perform the fill fillrect8_hook(dest_X, dest_Y, dest_X_max, dest_Y_max, color); } static void accl_fillrect32(accl_params *p) { D(bug("accl_fillrect32\n")); // Get filling parameters int16 dest_X = p->dest_rect[1] - p->dest_bounds[1]; int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0]; int16 dest_X_max = p->dest_rect[3] - p->dest_bounds[1] - 1; int16 dest_Y_max = p->dest_rect[2] - p->dest_bounds[0] - 1; uint32 color = p->pen_mode == 8 ? p->fore_pen : p->back_pen; D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); D(bug(" dest X max %d, dest Y max %d\n", dest_X_max, dest_Y_max)); // And perform the fill fillrect32_hook(dest_X, dest_Y, dest_X_max, dest_Y_max, color); } static void accl_invrect(accl_params *p) { D(bug("accl_invrect\n")); // Get inversion parameters int16 dest_X = p->dest_rect[1] - p->dest_bounds[1]; int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0]; int16 dest_X_max = p->dest_rect[3] - p->dest_bounds[1] - 1; int16 dest_Y_max = p->dest_rect[2] - p->dest_bounds[0] - 1; D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); D(bug(" dest X max %d, dest Y max %d\n", dest_X_max, dest_Y_max)); //!!?? pen_mode == 14 // And perform the inversion invrect_hook(dest_X, dest_Y, dest_X_max, dest_Y_max); } static bool accl_fillrect_hook(accl_params *p) { D(bug("accl_fillrect_hook %p\n", p)); // Check if we can accelerate this fillrect if (p->dest_base_addr == screen_base && ((uint32 *)p)[0x284 >> 2] != 0 && display_type == DIS_SCREEN) { if (p->transfer_mode == 8) { // Fill if (p->dest_pixel_size == 8 && fillrect8_hook != NULL) { p->draw_proc = accl_fillrect8; return true; } else if (p->dest_pixel_size == 32 && fillrect32_hook != NULL) { p->draw_proc = accl_fillrect32; return true; } } else if (p->transfer_mode == 10 && invrect_hook != NULL) { // Invert p->draw_proc = accl_invrect; return true; } } return false; } // Dummy for testing /* static void do_nothing(accl_params *p) {} static bool accl_foobar_hook(accl_params *p) { printf("accl_foobar_hook %p\n", p); printf(" src_base_addr %p, dest_base_addr %p\n", p->src_base_addr, p->dest_base_addr); printf(" src_row_bytes %d, dest_row_bytes %d\n", p->src_row_bytes, p->dest_row_bytes); printf(" src_pixel_size %d, dest_pixel_size %d\n", p->src_pixel_size, p->dest_pixel_size); printf(" src_bounds (%d,%d,%d,%d), dest_bounds (%d,%d,%d,%d)\n", p->src_bounds[0], p->src_bounds[1], p->src_bounds[2], p->src_bounds[3], p->dest_bounds[0], p->dest_bounds[1], p->dest_bounds[2], p->dest_bounds[3]); printf(" src_rect (%d,%d,%d,%d), dest_rect (%d,%d,%d,%d)\n", p->src_rect[0], p->src_rect[1], p->src_rect[2], p->src_rect[3], p->dest_rect[0], p->dest_rect[1], p->dest_rect[2], p->dest_rect[3]); printf(" transfer mode %d\n", p->transfer_mode); printf(" pen mode %d\n", p->pen_mode); printf(" fore_pen %08x, back_pen %08x\n", p->fore_pen, p->back_pen); printf(" val1 %08x, val2 %08x\n", ((uint32 *)p)[0x18 >> 2], ((uint32 *)p)[0x128 >> 2]); printf(" val3 %08x\n", ((uint32 *)p)[0x130 >> 2]); printf(" val4 %08x\n", ((uint32 *)p)[0x15c >> 2]); printf(" val5 %08x\n", ((uint32 *)p)[0x160 >> 2]); printf(" val6 %08x\n", ((uint32 *)p)[0x1b4 >> 2]); printf(" val7 %08x\n", ((uint32 *)p)[0x284 >> 2]); p->draw_proc = do_nothing; return true; } static struct accl_hook_info foobar_hook_info = {accl_foobar_hook, accl_sync_hook, 6}; */ // Wait for graphics operation to finish static bool accl_sync_hook(void *arg) { D(bug("accl_sync_hook %p\n", arg)); if (sync_hook != NULL) sync_hook(); return true; } static struct accl_hook_info bitblt_hook_info = {accl_bitblt_hook, accl_sync_hook, ACCL_BITBLT}; static struct accl_hook_info fillrect_hook_info = {accl_fillrect_hook, accl_sync_hook, ACCL_FILLRECT}; void VideoInstallAccel(void) { // Install acceleration hooks if (PrefsFindBool("gfxaccel")) { D(bug("Video: Installing acceleration hooks\n")); NQDMisc(6, &bitblt_hook_info); NQDMisc(6, &fillrect_hook_info); } } /* * Change video mode */ int16 video_mode_change(VidLocals *csSave, uint32 ParamPtr) { /* return if no mode change */ if ((csSave->saveData == ReadMacInt32(ParamPtr + csData)) && (csSave->saveMode == ReadMacInt16(ParamPtr + csMode))) return noErr; /* first find video mode in table */ for (int i=0; VModes[i].viType != DIS_INVALID; i++) { if ((ReadMacInt16(ParamPtr + csMode) == VModes[i].viAppleMode) && (ReadMacInt32(ParamPtr + csData) == VModes[i].viAppleID)) { csSave->saveMode = ReadMacInt16(ParamPtr + csMode); csSave->saveData = ReadMacInt32(ParamPtr + csData); csSave->savePage = ReadMacInt16(ParamPtr + csPage); while (acquire_sem(video_lock) == B_INTERRUPTED) ; DisableInterrupt(); /* close old display */ close_display(); /* open new display */ cur_mode = i; open_display(); /* opening the screen failed? Then bail out */ if (display_type == DIS_SCREEN && the_screen == NULL) { release_sem(video_lock); ErrorAlert(GetString(STR_FULL_SCREEN_ERR)); QuitEmulator(); } WriteMacInt32(ParamPtr + csBaseAddr, screen_base); csSave->saveBaseAddr=screen_base; csSave->saveData=VModes[cur_mode].viAppleID;/* First mode ... */ csSave->saveMode=VModes[cur_mode].viAppleMode; EnableInterrupt(); release_sem(video_lock); return noErr; } } return paramErr; } /* * Set color palette */ void video_set_palette(void) { if (display_type == DIS_SCREEN && the_screen != NULL) the_screen->palette_changed = true; else { // remap colors to BeOS-Palette BScreen screen; for (int i=0;i<256;i++) remap_mac_be[i]=screen.IndexForColor(mac_pal[i].red,mac_pal[i].green,mac_pal[i].blue); } } /* * Set cursor image for window */ void video_set_cursor(void) { the_window->cursor_changed = true; // Inform window (don't set cursor directly because this may run at interrupt (i.e. signal handler) time) }