1 |
/* |
2 |
* video_beos.cpp - Video/graphics emulation, BeOS specific things |
3 |
* |
4 |
* SheepShaver (C) 1997-2002 Marc Hellwig and Christian Bauer |
5 |
* |
6 |
* This program is free software; you can redistribute it and/or modify |
7 |
* it under the terms of the GNU General Public License as published by |
8 |
* the Free Software Foundation; either version 2 of the License, or |
9 |
* (at your option) any later version. |
10 |
* |
11 |
* This program is distributed in the hope that it will be useful, |
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
* GNU General Public License for more details. |
15 |
* |
16 |
* You should have received a copy of the GNU General Public License |
17 |
* along with this program; if not, write to the Free Software |
18 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 |
*/ |
20 |
|
21 |
#include "sysdeps.h" |
22 |
|
23 |
#include "video.h" |
24 |
#include "video_defs.h" |
25 |
#include "main.h" |
26 |
#include "adb.h" |
27 |
#include "prefs.h" |
28 |
#include "user_strings.h" |
29 |
#include "about_window.h" |
30 |
#include "version.h" |
31 |
|
32 |
#define DEBUG 0 |
33 |
#include "debug.h" |
34 |
|
35 |
|
36 |
// Global variables |
37 |
static sem_id video_lock = -1; // Protection during mode changes |
38 |
static sem_id mac_os_lock = -1; // This is used to stop the MacOS thread when the SheepShaver workspace is switched out |
39 |
|
40 |
// Prototypes |
41 |
static filter_result filter_func(BMessage *msg, BHandler **target, BMessageFilter *filter); |
42 |
|
43 |
// From sys_beos.cpp |
44 |
extern void SysCreateVolumeMenu(BMenu *menu, uint32 msg); |
45 |
extern void SysMountVolume(const char *name); |
46 |
|
47 |
|
48 |
#include "video_window.h" |
49 |
#include "video_screen.h" |
50 |
|
51 |
|
52 |
/* |
53 |
* Display manager thread (for opening and closing windows and screens; |
54 |
* this is not safe under R4 when running on the MacOS stack in kernel |
55 |
* space) |
56 |
*/ |
57 |
|
58 |
// Message constants |
59 |
const uint32 MSG_OPEN_WINDOW = 'owin'; |
60 |
const uint32 MSG_CLOSE_WINDOW = 'cwin'; |
61 |
const uint32 MSG_OPEN_SCREEN = 'oscr'; |
62 |
const uint32 MSG_CLOSE_SCREEN = 'cscr'; |
63 |
const uint32 MSG_QUIT_DISPLAY_MANAGER = 'quit'; |
64 |
|
65 |
static thread_id dm_thread = -1; |
66 |
static sem_id dm_done_sem = -1; |
67 |
|
68 |
static status_t display_manager(void *arg) |
69 |
{ |
70 |
for (;;) { |
71 |
|
72 |
// Receive message |
73 |
thread_id sender; |
74 |
uint32 code = receive_data(&sender, NULL, 0); |
75 |
D(bug("Display manager received %08lx\n", code)); |
76 |
switch (code) { |
77 |
case MSG_QUIT_DISPLAY_MANAGER: |
78 |
return 0; |
79 |
|
80 |
case MSG_OPEN_WINDOW: |
81 |
D(bug("Opening window\n")); |
82 |
the_window = new MacWindow(BRect(0, 0, VModes[cur_mode].viXsize-1, VModes[cur_mode].viYsize-1)); |
83 |
D(bug("Opened\n")); |
84 |
break; |
85 |
|
86 |
case MSG_CLOSE_WINDOW: |
87 |
if (the_window != NULL) { |
88 |
D(bug("Posting quit to window\n")); |
89 |
the_window->PostMessage(B_QUIT_REQUESTED); |
90 |
D(bug("Posted, waiting\n")); |
91 |
while (the_window) |
92 |
snooze(200000); |
93 |
D(bug("Window closed\n")); |
94 |
} |
95 |
break; |
96 |
|
97 |
case MSG_OPEN_SCREEN: { |
98 |
D(bug("Opening screen\n")); |
99 |
long scr_mode = 0; |
100 |
switch (VModes[cur_mode].viAppleMode) { |
101 |
case APPLE_8_BIT: |
102 |
switch (VModes[cur_mode].viAppleID) { |
103 |
case APPLE_640x480: |
104 |
scr_mode = B_8_BIT_640x480; |
105 |
break; |
106 |
case APPLE_800x600: |
107 |
scr_mode = B_8_BIT_800x600; |
108 |
break; |
109 |
case APPLE_1024x768: |
110 |
scr_mode = B_8_BIT_1024x768; |
111 |
break; |
112 |
case APPLE_1152x900: |
113 |
scr_mode = B_8_BIT_1152x900; |
114 |
break; |
115 |
case APPLE_1280x1024: |
116 |
scr_mode = B_8_BIT_1280x1024; |
117 |
break; |
118 |
case APPLE_1600x1200: |
119 |
scr_mode = B_8_BIT_1600x1200; |
120 |
break; |
121 |
} |
122 |
break; |
123 |
case APPLE_16_BIT: |
124 |
switch (VModes[cur_mode].viAppleID) { |
125 |
case APPLE_640x480: |
126 |
scr_mode = B_15_BIT_640x480; |
127 |
break; |
128 |
case APPLE_800x600: |
129 |
scr_mode = B_15_BIT_800x600; |
130 |
break; |
131 |
case APPLE_1024x768: |
132 |
scr_mode = B_15_BIT_1024x768; |
133 |
break; |
134 |
case APPLE_1152x900: |
135 |
scr_mode = B_15_BIT_1152x900; |
136 |
break; |
137 |
case APPLE_1280x1024: |
138 |
scr_mode = B_15_BIT_1280x1024; |
139 |
break; |
140 |
case APPLE_1600x1200: |
141 |
scr_mode = B_15_BIT_1600x1200; |
142 |
break; |
143 |
} |
144 |
break; |
145 |
case APPLE_32_BIT: |
146 |
switch (VModes[cur_mode].viAppleID) { |
147 |
case APPLE_640x480: |
148 |
scr_mode = B_32_BIT_640x480; |
149 |
break; |
150 |
case APPLE_800x600: |
151 |
scr_mode = B_32_BIT_800x600; |
152 |
break; |
153 |
case APPLE_1024x768: |
154 |
scr_mode = B_32_BIT_1024x768; |
155 |
break; |
156 |
case APPLE_1152x900: |
157 |
scr_mode = B_32_BIT_1152x900; |
158 |
break; |
159 |
case APPLE_1280x1024: |
160 |
scr_mode = B_32_BIT_1280x1024; |
161 |
break; |
162 |
case APPLE_1600x1200: |
163 |
scr_mode = B_32_BIT_1600x1200; |
164 |
break; |
165 |
} |
166 |
break; |
167 |
} |
168 |
the_screen = new MacScreen(GetString(STR_WINDOW_TITLE), scr_mode); |
169 |
D(bug("Opened, error %08lx\n", screen_error)); |
170 |
if (screen_error != B_NO_ERROR) { |
171 |
D(bug("Error, posting quit to screen\n")); |
172 |
the_screen->PostMessage(B_QUIT_REQUESTED); |
173 |
D(bug("Posted, waiting\n")); |
174 |
while (the_screen) |
175 |
snooze(200000); |
176 |
D(bug("Screen closed\n")); |
177 |
break; |
178 |
} |
179 |
|
180 |
// Wait for video mem access |
181 |
D(bug("Showing screen\n")); |
182 |
the_screen->Show(); |
183 |
D(bug("Shown, waiting for frame buffer access\n")); |
184 |
while (!drawing_enable) |
185 |
snooze(200000); |
186 |
D(bug("Access granted\n")); |
187 |
break; |
188 |
} |
189 |
|
190 |
case MSG_CLOSE_SCREEN: |
191 |
if (the_screen != NULL) { |
192 |
D(bug("Posting quit to screen\n")); |
193 |
the_screen->PostMessage(B_QUIT_REQUESTED); |
194 |
D(bug("Posted, waiting\n")); |
195 |
while (the_screen) |
196 |
snooze(200000); |
197 |
D(bug("Screen closed\n")); |
198 |
} |
199 |
break; |
200 |
} |
201 |
|
202 |
// Acknowledge |
203 |
release_sem(dm_done_sem); |
204 |
} |
205 |
} |
206 |
|
207 |
|
208 |
/* |
209 |
* Open display (window or screen) |
210 |
*/ |
211 |
|
212 |
static void open_display(void) |
213 |
{ |
214 |
D(bug("entering open_display()\n")); |
215 |
display_type = VModes[cur_mode].viType; |
216 |
if (display_type == DIS_SCREEN) { |
217 |
while (send_data(dm_thread, MSG_OPEN_SCREEN, NULL, 0) == B_INTERRUPTED) ; |
218 |
while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ; |
219 |
} else if (display_type == DIS_WINDOW) { |
220 |
while (send_data(dm_thread, MSG_OPEN_WINDOW, NULL, 0) == B_INTERRUPTED) ; |
221 |
while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ; |
222 |
} |
223 |
D(bug("exiting open_display()\n")); |
224 |
} |
225 |
|
226 |
|
227 |
/* |
228 |
* Close display |
229 |
*/ |
230 |
|
231 |
static void close_display(void) |
232 |
{ |
233 |
D(bug("entering close_display()\n")); |
234 |
if (display_type == DIS_SCREEN) { |
235 |
while (send_data(dm_thread, MSG_CLOSE_SCREEN, NULL, 0) == B_INTERRUPTED) ; |
236 |
while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ; |
237 |
} else if (display_type == DIS_WINDOW) { |
238 |
while (send_data(dm_thread, MSG_CLOSE_WINDOW, NULL, 0) == B_INTERRUPTED) ; |
239 |
while (acquire_sem(dm_done_sem) == B_INTERRUPTED) ; |
240 |
} |
241 |
D(bug("exiting close_display()\n")); |
242 |
} |
243 |
|
244 |
|
245 |
/* |
246 |
* Initialization |
247 |
*/ |
248 |
|
249 |
static void add_mode(VideoInfo *&p, uint32 allow, uint32 test, long apple_mode, long apple_id, int type) |
250 |
{ |
251 |
if (allow & test) { |
252 |
p->viType = type; |
253 |
switch (apple_id) { |
254 |
case APPLE_W_640x480: |
255 |
case APPLE_640x480: |
256 |
p->viXsize = 640; |
257 |
p->viYsize = 480; |
258 |
break; |
259 |
case APPLE_W_800x600: |
260 |
case APPLE_800x600: |
261 |
p->viXsize = 800; |
262 |
p->viYsize = 600; |
263 |
break; |
264 |
case APPLE_1024x768: |
265 |
p->viXsize = 1024; |
266 |
p->viYsize = 768; |
267 |
break; |
268 |
case APPLE_1152x900: |
269 |
p->viXsize = 1152; |
270 |
p->viYsize = 900; |
271 |
break; |
272 |
case APPLE_1280x1024: |
273 |
p->viXsize = 1280; |
274 |
p->viYsize = 1024; |
275 |
break; |
276 |
case APPLE_1600x1200: |
277 |
p->viXsize = 1600; |
278 |
p->viYsize = 1200; |
279 |
break; |
280 |
} |
281 |
switch (apple_mode) { |
282 |
case APPLE_8_BIT: |
283 |
p->viRowBytes = p->viXsize; |
284 |
break; |
285 |
case APPLE_16_BIT: |
286 |
p->viRowBytes = p->viXsize * 2; |
287 |
break; |
288 |
case APPLE_32_BIT: |
289 |
p->viRowBytes = p->viXsize * 4; |
290 |
break; |
291 |
} |
292 |
p->viAppleMode = apple_mode; |
293 |
p->viAppleID = apple_id; |
294 |
p++; |
295 |
} |
296 |
} |
297 |
|
298 |
bool VideoInit(void) |
299 |
{ |
300 |
// Init variables, create semaphores |
301 |
private_data = NULL; |
302 |
cur_mode = 0; // Window 640x480 |
303 |
video_lock = create_sem(1, "Video Lock"); |
304 |
mac_os_lock = create_sem(0, "MacOS Frame Buffer Lock"); |
305 |
dm_done_sem = create_sem(0, "Display Manager Done"); |
306 |
|
307 |
// Construct video mode table |
308 |
VideoInfo *p = VModes; |
309 |
uint32 window_modes = PrefsFindInt32("windowmodes"); |
310 |
uint32 screen_modes = PrefsFindInt32("screenmodes"); |
311 |
if (window_modes == 0 && screen_modes == 0) |
312 |
window_modes |= B_8_BIT_640x480 | B_8_BIT_800x600; // Allow at least 640x480 and 800x600 window modes |
313 |
add_mode(p, window_modes, B_8_BIT_640x480, APPLE_8_BIT, APPLE_W_640x480, DIS_WINDOW); |
314 |
add_mode(p, window_modes, B_8_BIT_800x600, APPLE_8_BIT, APPLE_W_800x600, DIS_WINDOW); |
315 |
add_mode(p, window_modes, B_15_BIT_640x480, APPLE_16_BIT, APPLE_W_640x480, DIS_WINDOW); |
316 |
add_mode(p, window_modes, B_15_BIT_800x600, APPLE_16_BIT, APPLE_W_800x600, DIS_WINDOW); |
317 |
add_mode(p, window_modes, B_32_BIT_640x480, APPLE_32_BIT, APPLE_W_640x480, DIS_WINDOW); |
318 |
add_mode(p, window_modes, B_32_BIT_800x600, APPLE_32_BIT, APPLE_W_800x600, DIS_WINDOW); |
319 |
add_mode(p, screen_modes, B_8_BIT_640x480, APPLE_8_BIT, APPLE_640x480, DIS_SCREEN); |
320 |
add_mode(p, screen_modes, B_8_BIT_800x600, APPLE_8_BIT, APPLE_800x600, DIS_SCREEN); |
321 |
add_mode(p, screen_modes, B_8_BIT_1024x768, APPLE_8_BIT, APPLE_1024x768, DIS_SCREEN); |
322 |
add_mode(p, screen_modes, B_8_BIT_1152x900, APPLE_8_BIT, APPLE_1152x900, DIS_SCREEN); |
323 |
add_mode(p, screen_modes, B_8_BIT_1280x1024, APPLE_8_BIT, APPLE_1280x1024, DIS_SCREEN); |
324 |
add_mode(p, screen_modes, B_8_BIT_1600x1200, APPLE_8_BIT, APPLE_1600x1200, DIS_SCREEN); |
325 |
add_mode(p, screen_modes, B_15_BIT_640x480, APPLE_16_BIT, APPLE_640x480, DIS_SCREEN); |
326 |
add_mode(p, screen_modes, B_15_BIT_800x600, APPLE_16_BIT, APPLE_800x600, DIS_SCREEN); |
327 |
add_mode(p, screen_modes, B_15_BIT_1024x768, APPLE_16_BIT, APPLE_1024x768, DIS_SCREEN); |
328 |
add_mode(p, screen_modes, B_15_BIT_1152x900, APPLE_16_BIT, APPLE_1152x900, DIS_SCREEN); |
329 |
add_mode(p, screen_modes, B_15_BIT_1280x1024, APPLE_16_BIT, APPLE_1280x1024, DIS_SCREEN); |
330 |
add_mode(p, screen_modes, B_15_BIT_1600x1200, APPLE_16_BIT, APPLE_1600x1200, DIS_SCREEN); |
331 |
add_mode(p, screen_modes, B_32_BIT_640x480, APPLE_32_BIT, APPLE_640x480, DIS_SCREEN); |
332 |
add_mode(p, screen_modes, B_32_BIT_800x600, APPLE_32_BIT, APPLE_800x600, DIS_SCREEN); |
333 |
add_mode(p, screen_modes, B_32_BIT_1024x768, APPLE_32_BIT, APPLE_1024x768, DIS_SCREEN); |
334 |
add_mode(p, screen_modes, B_32_BIT_1152x900, APPLE_32_BIT, APPLE_1152x900, DIS_SCREEN); |
335 |
add_mode(p, screen_modes, B_32_BIT_1280x1024, APPLE_32_BIT, APPLE_1280x1024, DIS_SCREEN); |
336 |
add_mode(p, screen_modes, B_32_BIT_1600x1200, APPLE_32_BIT, APPLE_1600x1200, DIS_SCREEN); |
337 |
p->viType = DIS_INVALID; // End marker |
338 |
p->viRowBytes = 0; |
339 |
p->viXsize = p->viYsize = 0; |
340 |
p->viAppleMode = 0; |
341 |
p->viAppleID = 0; |
342 |
|
343 |
// Start display manager thread |
344 |
dm_thread = spawn_thread(display_manager, "Display Manager", B_NORMAL_PRIORITY, NULL); |
345 |
resume_thread(dm_thread); |
346 |
|
347 |
// Open window/screen |
348 |
open_display(); |
349 |
if (display_type == DIS_SCREEN && the_screen == NULL) { |
350 |
char str[256]; |
351 |
sprintf(str, GetString(STR_FULL_SCREEN_ERR), strerror(screen_error), screen_error); |
352 |
ErrorAlert(str); |
353 |
return false; |
354 |
} |
355 |
return true; |
356 |
} |
357 |
|
358 |
|
359 |
/* |
360 |
* Deinitialization |
361 |
*/ |
362 |
|
363 |
void VideoExit(void) |
364 |
{ |
365 |
if (dm_thread >= 0) { |
366 |
|
367 |
// Close display |
368 |
acquire_sem(video_lock); |
369 |
close_display(); |
370 |
if (private_data != NULL) { |
371 |
delete private_data->gammaTable; |
372 |
delete private_data; |
373 |
} |
374 |
|
375 |
// Stop display manager |
376 |
status_t l; |
377 |
send_data(dm_thread, MSG_QUIT_DISPLAY_MANAGER, NULL, 0); |
378 |
while (wait_for_thread(dm_thread, &l) == B_INTERRUPTED) ; |
379 |
} |
380 |
|
381 |
// Delete semaphores |
382 |
delete_sem(video_lock); |
383 |
delete_sem(mac_os_lock); |
384 |
delete_sem(dm_done_sem); |
385 |
} |
386 |
|
387 |
|
388 |
/* |
389 |
* Close screen in full-screen mode |
390 |
*/ |
391 |
|
392 |
void VideoQuitFullScreen(void) |
393 |
{ |
394 |
D(bug("VideoQuitFullScreen()\n")); |
395 |
if (display_type == DIS_SCREEN) { |
396 |
acquire_sem(video_lock); |
397 |
close_display(); |
398 |
release_sem(video_lock); |
399 |
} |
400 |
} |
401 |
|
402 |
|
403 |
/* |
404 |
* Execute video VBL routine |
405 |
*/ |
406 |
|
407 |
void VideoVBL(void) |
408 |
{ |
409 |
release_sem(mac_os_lock); |
410 |
if (private_data != NULL && private_data->interruptsEnabled) |
411 |
VSLDoInterruptService(private_data->vslServiceID); |
412 |
while (acquire_sem(mac_os_lock) == B_INTERRUPTED) ; |
413 |
} |
414 |
|
415 |
|
416 |
/* |
417 |
* Filter function for receiving mouse and keyboard events |
418 |
*/ |
419 |
|
420 |
#define MENU_IS_POWER 0 |
421 |
|
422 |
// Be -> Mac raw keycode translation table |
423 |
static const uint8 keycode2mac[0x80] = { |
424 |
0xff, 0x35, 0x7a, 0x78, 0x63, 0x76, 0x60, 0x61, // inv Esc F1 F2 F3 F4 F5 F6 |
425 |
0x62, 0x64, 0x65, 0x6d, 0x67, 0x6f, 0x69, 0x6b, // F7 F8 F9 F10 F11 F12 F13 F14 |
426 |
0x71, 0x0a, 0x12, 0x13, 0x14, 0x15, 0x17, 0x16, // F15 ` 1 2 3 4 5 6 |
427 |
0x1a, 0x1c, 0x19, 0x1d, 0x1b, 0x18, 0x33, 0x72, // 7 8 9 0 - = BSP INS |
428 |
0x73, 0x74, 0x47, 0x4b, 0x43, 0x4e, 0x30, 0x0c, // HOM PUP NUM / * - TAB Q |
429 |
0x0d, 0x0e, 0x0f, 0x11, 0x10, 0x20, 0x22, 0x1f, // W E R T Y U I O |
430 |
0x23, 0x21, 0x1e, 0x2a, 0x75, 0x77, 0x79, 0x59, // P [ ] \ DEL END PDN 7 |
431 |
0x5b, 0x5c, 0x45, 0x39, 0x00, 0x01, 0x02, 0x03, // 8 9 + CAP A S D F |
432 |
0x05, 0x04, 0x26, 0x28, 0x25, 0x29, 0x27, 0x24, // G H J K L ; ' RET |
433 |
0x56, 0x57, 0x58, 0x38, 0x06, 0x07, 0x08, 0x09, // 4 5 6 SHL Z X C V |
434 |
0x0b, 0x2d, 0x2e, 0x2b, 0x2f, 0x2c, 0x38, 0x3e, // B N M , . / SHR CUP |
435 |
0x53, 0x54, 0x55, 0x4c, 0x36, 0x37, 0x31, 0x37, // 1 2 3 ENT CTL ALT SPC ALT |
436 |
0x36, 0x3b, 0x3d, 0x3c, 0x52, 0x41, 0x3a, 0x3a, // CTR CLF CDN CRT 0 . CMD CMD |
437 |
#if MENU_IS_POWER |
438 |
0x7f, 0x32, 0x51, 0x7f, 0xff, 0xff, 0xff, 0xff, // MNU EUR = POW inv inv inv inv |
439 |
#else |
440 |
0x32, 0x32, 0x51, 0x7f, 0xff, 0xff, 0xff, 0xff, // MNU EUR = POW inv inv inv inv |
441 |
#endif |
442 |
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv |
443 |
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // inv inv inv inv inv inv inv inv |
444 |
}; |
445 |
|
446 |
static const uint8 modifier2mac[0x20] = { |
447 |
#if MENU_IS_POWER |
448 |
0x38, 0x37, 0x36, 0x39, 0x6b, 0x47, 0x3a, 0x7f, // SHF CMD inv CAP F14 NUM OPT MNU |
449 |
#else |
450 |
0x38, 0x37, 0x36, 0x39, 0x6b, 0x47, 0x3a, 0x32, // SHF CMD CTR CAP F14 NUM OPT MNU |
451 |
#endif |
452 |
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv |
453 |
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv |
454 |
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // inv inv inv inv inv inv inv inv |
455 |
}; |
456 |
|
457 |
static filter_result filter_func(BMessage *msg, BHandler **target, BMessageFilter *filter) |
458 |
{ |
459 |
// msg->PrintToStream(); |
460 |
switch (msg->what) { |
461 |
case B_KEY_DOWN: |
462 |
case B_KEY_UP: { |
463 |
uint32 be_code = msg->FindInt32("key") & 0xff; |
464 |
uint32 mac_code = keycode2mac[be_code]; |
465 |
|
466 |
// Intercept Ctrl-F1 (mount floppy disk shortcut) |
467 |
uint32 mods = msg->FindInt32("modifiers"); |
468 |
if (be_code == 0x02 && (mods & B_CONTROL_KEY)) |
469 |
SysMountVolume("/dev/disk/floppy/raw"); |
470 |
|
471 |
if (mac_code == 0xff) |
472 |
return B_DISPATCH_MESSAGE; |
473 |
if (msg->what == B_KEY_DOWN) |
474 |
ADBKeyDown(mac_code); |
475 |
else |
476 |
ADBKeyUp(mac_code); |
477 |
return B_SKIP_MESSAGE; |
478 |
} |
479 |
|
480 |
case B_MODIFIERS_CHANGED: { |
481 |
uint32 mods = msg->FindInt32("modifiers"); |
482 |
uint32 old_mods = msg->FindInt32("be:old_modifiers"); |
483 |
uint32 changed = mods ^ old_mods; |
484 |
uint32 mask = 1; |
485 |
for (int i=0; i<32; i++, mask<<=1) |
486 |
if (changed & mask) { |
487 |
uint32 mac_code = modifier2mac[i]; |
488 |
if (mac_code == 0xff) |
489 |
continue; |
490 |
if (mods & mask) |
491 |
ADBKeyDown(mac_code); |
492 |
else |
493 |
ADBKeyUp(mac_code); |
494 |
} |
495 |
return B_SKIP_MESSAGE; |
496 |
} |
497 |
|
498 |
case B_MOUSE_MOVED: { |
499 |
BPoint point; |
500 |
msg->FindPoint("where", &point); |
501 |
ADBMouseMoved(int(point.x), int(point.y)); |
502 |
return B_DISPATCH_MESSAGE; // Otherwise BitmapView::MouseMoved() wouldn't be called |
503 |
} |
504 |
|
505 |
case B_MOUSE_DOWN: { |
506 |
uint32 buttons = msg->FindInt32("buttons"); |
507 |
if (buttons & B_PRIMARY_MOUSE_BUTTON) |
508 |
ADBMouseDown(0); |
509 |
if (buttons & B_SECONDARY_MOUSE_BUTTON) |
510 |
ADBMouseDown(1); |
511 |
if (buttons & B_TERTIARY_MOUSE_BUTTON) |
512 |
ADBMouseDown(2); |
513 |
return B_SKIP_MESSAGE; |
514 |
} |
515 |
|
516 |
case B_MOUSE_UP: // B_MOUSE_UP means "all buttons released" |
517 |
ADBMouseUp(0); |
518 |
ADBMouseUp(1); |
519 |
ADBMouseUp(2); |
520 |
return B_SKIP_MESSAGE; |
521 |
|
522 |
default: |
523 |
return B_DISPATCH_MESSAGE; |
524 |
} |
525 |
} |
526 |
|
527 |
|
528 |
/* |
529 |
* Install graphics acceleration |
530 |
*/ |
531 |
|
532 |
// Rectangle blitting |
533 |
static void accl_bitblt(accl_params *p) |
534 |
{ |
535 |
D(bug("accl_bitblt\n")); |
536 |
|
537 |
// Get blitting parameters |
538 |
int16 src_X = p->src_rect[1] - p->src_bounds[1]; |
539 |
int16 src_Y = p->src_rect[0] - p->src_bounds[0]; |
540 |
int16 dest_X = p->dest_rect[1] - p->dest_bounds[1]; |
541 |
int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0]; |
542 |
int16 width = p->dest_rect[3] - p->dest_rect[1] - 1; |
543 |
int16 height = p->dest_rect[2] - p->dest_rect[0] - 1; |
544 |
D(bug(" src X %d, src Y %d, dest X %d, dest Y %d\n", src_X, src_Y, dest_X, dest_Y)); |
545 |
D(bug(" width %d, height %d\n", width, height)); |
546 |
|
547 |
// And perform the blit |
548 |
bitblt_hook(src_X, src_Y, dest_X, dest_Y, width, height); |
549 |
} |
550 |
|
551 |
static bool accl_bitblt_hook(accl_params *p) |
552 |
{ |
553 |
D(bug("accl_draw_hook %p\n", p)); |
554 |
|
555 |
// Check if we can accelerate this bitblt |
556 |
if (p->src_base_addr == screen_base && p->dest_base_addr == screen_base && |
557 |
display_type == DIS_SCREEN && bitblt_hook != NULL && |
558 |
((uint32 *)p)[0x18 >> 2] + ((uint32 *)p)[0x128 >> 2] == 0 && |
559 |
((uint32 *)p)[0x130 >> 2] == 0 && |
560 |
p->transfer_mode == 0 && |
561 |
p->src_row_bytes > 0 && ((uint32 *)p)[0x15c >> 2] > 0) { |
562 |
|
563 |
// Yes, set function pointer |
564 |
p->draw_proc = accl_bitblt; |
565 |
return true; |
566 |
} |
567 |
return false; |
568 |
} |
569 |
|
570 |
// Rectangle filling/inversion |
571 |
static void accl_fillrect8(accl_params *p) |
572 |
{ |
573 |
D(bug("accl_fillrect8\n")); |
574 |
|
575 |
// Get filling parameters |
576 |
int16 dest_X = p->dest_rect[1] - p->dest_bounds[1]; |
577 |
int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0]; |
578 |
int16 dest_X_max = p->dest_rect[3] - p->dest_bounds[1] - 1; |
579 |
int16 dest_Y_max = p->dest_rect[2] - p->dest_bounds[0] - 1; |
580 |
uint8 color = p->pen_mode == 8 ? p->fore_pen : p->back_pen; |
581 |
D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); |
582 |
D(bug(" dest X max %d, dest Y max %d\n", dest_X_max, dest_Y_max)); |
583 |
|
584 |
// And perform the fill |
585 |
fillrect8_hook(dest_X, dest_Y, dest_X_max, dest_Y_max, color); |
586 |
} |
587 |
|
588 |
static void accl_fillrect32(accl_params *p) |
589 |
{ |
590 |
D(bug("accl_fillrect32\n")); |
591 |
|
592 |
// Get filling parameters |
593 |
int16 dest_X = p->dest_rect[1] - p->dest_bounds[1]; |
594 |
int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0]; |
595 |
int16 dest_X_max = p->dest_rect[3] - p->dest_bounds[1] - 1; |
596 |
int16 dest_Y_max = p->dest_rect[2] - p->dest_bounds[0] - 1; |
597 |
uint32 color = p->pen_mode == 8 ? p->fore_pen : p->back_pen; |
598 |
D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); |
599 |
D(bug(" dest X max %d, dest Y max %d\n", dest_X_max, dest_Y_max)); |
600 |
|
601 |
// And perform the fill |
602 |
fillrect32_hook(dest_X, dest_Y, dest_X_max, dest_Y_max, color); |
603 |
} |
604 |
|
605 |
static void accl_invrect(accl_params *p) |
606 |
{ |
607 |
D(bug("accl_invrect\n")); |
608 |
|
609 |
// Get inversion parameters |
610 |
int16 dest_X = p->dest_rect[1] - p->dest_bounds[1]; |
611 |
int16 dest_Y = p->dest_rect[0] - p->dest_bounds[0]; |
612 |
int16 dest_X_max = p->dest_rect[3] - p->dest_bounds[1] - 1; |
613 |
int16 dest_Y_max = p->dest_rect[2] - p->dest_bounds[0] - 1; |
614 |
D(bug(" dest X %d, dest Y %d\n", dest_X, dest_Y)); |
615 |
D(bug(" dest X max %d, dest Y max %d\n", dest_X_max, dest_Y_max)); |
616 |
|
617 |
//!!?? pen_mode == 14 |
618 |
|
619 |
// And perform the inversion |
620 |
invrect_hook(dest_X, dest_Y, dest_X_max, dest_Y_max); |
621 |
} |
622 |
|
623 |
static bool accl_fillrect_hook(accl_params *p) |
624 |
{ |
625 |
D(bug("accl_fillrect_hook %p\n", p)); |
626 |
|
627 |
// Check if we can accelerate this fillrect |
628 |
if (p->dest_base_addr == screen_base && ((uint32 *)p)[0x284 >> 2] != 0 && display_type == DIS_SCREEN) { |
629 |
if (p->transfer_mode == 8) { |
630 |
// Fill |
631 |
if (p->dest_pixel_size == 8 && fillrect8_hook != NULL) { |
632 |
p->draw_proc = accl_fillrect8; |
633 |
return true; |
634 |
} else if (p->dest_pixel_size == 32 && fillrect32_hook != NULL) { |
635 |
p->draw_proc = accl_fillrect32; |
636 |
return true; |
637 |
} |
638 |
} else if (p->transfer_mode == 10 && invrect_hook != NULL) { |
639 |
// Invert |
640 |
p->draw_proc = accl_invrect; |
641 |
return true; |
642 |
} |
643 |
} |
644 |
return false; |
645 |
} |
646 |
|
647 |
// Dummy for testing |
648 |
/* |
649 |
static void do_nothing(accl_params *p) {} |
650 |
static bool accl_foobar_hook(accl_params *p) |
651 |
{ |
652 |
printf("accl_foobar_hook %p\n", p); |
653 |
printf(" src_base_addr %p, dest_base_addr %p\n", p->src_base_addr, p->dest_base_addr); |
654 |
printf(" src_row_bytes %d, dest_row_bytes %d\n", p->src_row_bytes, p->dest_row_bytes); |
655 |
printf(" src_pixel_size %d, dest_pixel_size %d\n", p->src_pixel_size, p->dest_pixel_size); |
656 |
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]); |
657 |
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]); |
658 |
printf(" transfer mode %d\n", p->transfer_mode); |
659 |
printf(" pen mode %d\n", p->pen_mode); |
660 |
printf(" fore_pen %08x, back_pen %08x\n", p->fore_pen, p->back_pen); |
661 |
printf(" val1 %08x, val2 %08x\n", ((uint32 *)p)[0x18 >> 2], ((uint32 *)p)[0x128 >> 2]); |
662 |
printf(" val3 %08x\n", ((uint32 *)p)[0x130 >> 2]); |
663 |
printf(" val4 %08x\n", ((uint32 *)p)[0x15c >> 2]); |
664 |
printf(" val5 %08x\n", ((uint32 *)p)[0x160 >> 2]); |
665 |
printf(" val6 %08x\n", ((uint32 *)p)[0x1b4 >> 2]); |
666 |
printf(" val7 %08x\n", ((uint32 *)p)[0x284 >> 2]); |
667 |
p->draw_proc = do_nothing; |
668 |
return true; |
669 |
} |
670 |
static struct accl_hook_info foobar_hook_info = {accl_foobar_hook, accl_sync_hook, 6}; |
671 |
*/ |
672 |
|
673 |
// Wait for graphics operation to finish |
674 |
static bool accl_sync_hook(void *arg) |
675 |
{ |
676 |
D(bug("accl_sync_hook %p\n", arg)); |
677 |
if (sync_hook != NULL) |
678 |
sync_hook(); |
679 |
return true; |
680 |
} |
681 |
|
682 |
static struct accl_hook_info bitblt_hook_info = {accl_bitblt_hook, accl_sync_hook, ACCL_BITBLT}; |
683 |
static struct accl_hook_info fillrect_hook_info = {accl_fillrect_hook, accl_sync_hook, ACCL_FILLRECT}; |
684 |
|
685 |
void VideoInstallAccel(void) |
686 |
{ |
687 |
// Install acceleration hooks |
688 |
if (PrefsFindBool("gfxaccel")) { |
689 |
D(bug("Video: Installing acceleration hooks\n")); |
690 |
NQDMisc(6, &bitblt_hook_info); |
691 |
NQDMisc(6, &fillrect_hook_info); |
692 |
} |
693 |
} |
694 |
|
695 |
|
696 |
/* |
697 |
* Change video mode |
698 |
*/ |
699 |
|
700 |
int16 video_mode_change(VidLocals *csSave, uint32 ParamPtr) |
701 |
{ |
702 |
/* return if no mode change */ |
703 |
if ((csSave->saveData == ReadMacInt32(ParamPtr + csData)) && |
704 |
(csSave->saveMode == ReadMacInt16(ParamPtr + csMode))) return noErr; |
705 |
|
706 |
/* first find video mode in table */ |
707 |
for (int i=0; VModes[i].viType != DIS_INVALID; i++) { |
708 |
if ((ReadMacInt16(ParamPtr + csMode) == VModes[i].viAppleMode) && |
709 |
(ReadMacInt32(ParamPtr + csData) == VModes[i].viAppleID)) { |
710 |
csSave->saveMode = ReadMacInt16(ParamPtr + csMode); |
711 |
csSave->saveData = ReadMacInt32(ParamPtr + csData); |
712 |
csSave->savePage = ReadMacInt16(ParamPtr + csPage); |
713 |
|
714 |
while (acquire_sem(video_lock) == B_INTERRUPTED) ; |
715 |
DisableInterrupt(); |
716 |
|
717 |
/* close old display */ |
718 |
close_display(); |
719 |
|
720 |
/* open new display */ |
721 |
cur_mode = i; |
722 |
open_display(); |
723 |
|
724 |
/* opening the screen failed? Then bail out */ |
725 |
if (display_type == DIS_SCREEN && the_screen == NULL) { |
726 |
release_sem(video_lock); |
727 |
ErrorAlert(GetString(STR_FULL_SCREEN_ERR)); |
728 |
QuitEmulator(); |
729 |
} |
730 |
|
731 |
WriteMacInt32(ParamPtr + csBaseAddr, screen_base); |
732 |
csSave->saveBaseAddr=screen_base; |
733 |
csSave->saveData=VModes[cur_mode].viAppleID;/* First mode ... */ |
734 |
csSave->saveMode=VModes[cur_mode].viAppleMode; |
735 |
|
736 |
EnableInterrupt(); |
737 |
release_sem(video_lock); |
738 |
return noErr; |
739 |
} |
740 |
} |
741 |
return paramErr; |
742 |
} |
743 |
|
744 |
|
745 |
/* |
746 |
* Set color palette |
747 |
*/ |
748 |
|
749 |
void video_set_palette(void) |
750 |
{ |
751 |
if (display_type == DIS_SCREEN && the_screen != NULL) |
752 |
the_screen->palette_changed = true; |
753 |
else { // remap colors to BeOS-Palette |
754 |
BScreen screen; |
755 |
for (int i=0;i<256;i++) |
756 |
remap_mac_be[i]=screen.IndexForColor(mac_pal[i].red,mac_pal[i].green,mac_pal[i].blue); |
757 |
} |
758 |
} |
759 |
|
760 |
|
761 |
/* |
762 |
* Set cursor image for window |
763 |
*/ |
764 |
|
765 |
void video_set_cursor(void) |
766 |
{ |
767 |
the_window->cursor_changed = true; // Inform window (don't set cursor directly because this may run at interrupt (i.e. signal handler) time) |
768 |
} |