769 lines
23 KiB
C++
769 lines
23 KiB
C++
/*
|
|
* 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)
|
|
}
|