ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/AmigaOS/video_amiga.cpp
Revision: 1.13
Committed: 2001-06-27T19:03:35Z (23 years, 4 months ago) by cebix
Branch: MAIN
Changes since 1.12: +57 -31 lines
Log Message:
added infrastructure for resolution/depth switching (currently, all video
drivers only support one mode, the one selected by the user)

File Contents

# Content
1 /*
2 * video_amiga.cpp - Video/graphics emulation, AmigaOS specific stuff
3 *
4 * Basilisk II (C) 1997-2001 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 <exec/types.h>
22 #include <intuition/intuition.h>
23 #include <graphics/rastport.h>
24 #include <graphics/gfx.h>
25 #include <cybergraphics/cybergraphics.h>
26 #include <dos/dostags.h>
27 #include <devices/timer.h>
28 #include <proto/exec.h>
29 #include <proto/dos.h>
30 #include <proto/intuition.h>
31 #include <proto/graphics.h>
32 #include <proto/Picasso96.h>
33 #include <proto/cybergraphics.h>
34
35 #include "sysdeps.h"
36 #include "cpu_emulation.h"
37 #include "main.h"
38 #include "adb.h"
39 #include "prefs.h"
40 #include "user_strings.h"
41 #include "video.h"
42
43 #define DEBUG 0
44 #include "debug.h"
45
46
47 // Display types
48 enum {
49 DISPLAY_WINDOW,
50 DISPLAY_PIP,
51 DISPLAY_SCREEN_P96,
52 DISPLAY_SCREEN_CGFX
53 };
54
55 // Global variables
56 static int32 frame_skip;
57 static int display_type = DISPLAY_WINDOW; // See enum above
58 static struct Screen *the_screen = NULL;
59 static struct Window *the_win = NULL;
60 static struct BitMap *the_bitmap = NULL;
61 static UWORD *null_pointer = NULL; // Blank mouse pointer data
62 static UWORD *current_pointer = (UWORD *)-1; // Currently visible mouse pointer data
63 static LONG black_pen = -1, white_pen = -1;
64 static struct Process *periodic_proc = NULL; // Periodic process
65
66 extern struct Task *MainTask; // Pointer to main task (from main_amiga.cpp)
67
68
69 // Amiga -> Mac raw keycode translation table
70 static const uint8 keycode2mac[0x80] = {
71 0x0a, 0x12, 0x13, 0x14, 0x15, 0x17, 0x16, 0x1a, // ` 1 2 3 4 5 6 7
72 0x1c, 0x19, 0x1d, 0x1b, 0x18, 0x2a, 0xff, 0x52, // 8 9 0 - = \ inv 0
73 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x10, 0x20, 0x22, // Q W E R T Y U I
74 0x1f, 0x23, 0x21, 0x1e, 0xff, 0x53, 0x54, 0x55, // O P [ ] inv 1 2 3
75 0x00, 0x01, 0x02, 0x03, 0x05, 0x04, 0x26, 0x28, // A S D F G H J K
76 0x25, 0x29, 0x27, 0x2a, 0xff, 0x56, 0x57, 0x58, // L ; ' # inv 4 5 6
77 0x32, 0x06, 0x07, 0x08, 0x09, 0x0b, 0x2d, 0x2e, // < Z X C V B N M
78 0x2b, 0x2f, 0x2c, 0xff, 0x41, 0x59, 0x5b, 0x5c, // , . / inv . 7 8 9
79 0x31, 0x33, 0x30, 0x4c, 0x24, 0x35, 0x75, 0xff, // SPC BSP TAB ENT RET ESC DEL inv
80 0xff, 0xff, 0x4e, 0xff, 0x3e, 0x3d, 0x3c, 0x3b, // inv inv - inv CUP CDN CRT CLF
81 0x7a, 0x78, 0x63, 0x76, 0x60, 0x61, 0x62, 0x64, // F1 F2 F3 F4 F5 F6 F7 F8
82 0x65, 0x6d, 0x47, 0x51, 0x4b, 0x43, 0x45, 0x72, // F9 F10 ( ) / * + HLP
83 0x38, 0x38, 0x39, 0x36, 0x3a, 0x3a, 0x37, 0x37, // SHL SHR CAP CTL ALL ALR AML AMR
84 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv
85 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // inv inv inv inv inv inv inv inv
86 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff // inv inv inv inv inv inv inv inv
87 };
88
89
90 // Prototypes
91 static void periodic_func(void);
92
93
94 /*
95 * Initialization
96 */
97
98 // Add resolution to list of supported modes and set VideoMonitor
99 static void set_video_monitor(uint32 width, uint32 height, uint32 bytes_per_row, int depth)
100 {
101 video_mode mode;
102
103 mode.x = width;
104 mode.y = height;
105 mode.resolution_id = 0x80;
106 mode.bytes_per_row = bytes_per_row;
107
108 switch (depth) {
109 case 1:
110 mode.depth = VDEPTH_1BIT;
111 break;
112 case 2:
113 mode.depth = VDEPTH_2BIT;
114 break;
115 case 4:
116 mode.depth = VDEPTH_4BIT;
117 break;
118 case 8:
119 mode.depth = VDEPTH_8BIT;
120 break;
121 case 15:
122 mode.depth = VDEPTH_16BIT;
123 break;
124 case 16:
125 mode.depth = VDEPTH_16BIT;
126 break;
127 case 24:
128 case 32:
129 mode.depth = VDEPTH_32BIT;
130 break;
131 }
132
133 VideoModes.push_back(mode);
134 VideoMonitor.mode = mode;
135 }
136
137 // Open window
138 static bool init_window(int width, int height)
139 {
140 // Set absolute mouse mode
141 ADBSetRelMouseMode(false);
142
143 // Open window
144 the_win = OpenWindowTags(NULL,
145 WA_Left, 0, WA_Top, 0,
146 WA_InnerWidth, width, WA_InnerHeight, height,
147 WA_SimpleRefresh, TRUE,
148 WA_NoCareRefresh, TRUE,
149 WA_Activate, TRUE,
150 WA_RMBTrap, TRUE,
151 WA_ReportMouse, TRUE,
152 WA_DragBar, TRUE,
153 WA_DepthGadget, TRUE,
154 WA_SizeGadget, FALSE,
155 WA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
156 TAG_END
157 );
158 if (the_win == NULL) {
159 ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
160 return false;
161 }
162
163 // Create bitmap ("height + 2" for safety)
164 the_bitmap = AllocBitMap(width, height + 2, 1, BMF_CLEAR, NULL);
165 if (the_bitmap == NULL) {
166 ErrorAlert(GetString(STR_NO_MEM_ERR));
167 return false;
168 }
169
170 // Add resolution and set VideoMonitor
171 set_video_monitor(width, height, the_bitmap->BytesPerRow, 1);
172 VideoMonitor.mac_frame_base = (uint32)the_bitmap->Planes[0];
173
174 // Set FgPen and BgPen
175 black_pen = ObtainBestPenA(the_win->WScreen->ViewPort.ColorMap, 0, 0, 0, NULL);
176 white_pen = ObtainBestPenA(the_win->WScreen->ViewPort.ColorMap, 0xffffffff, 0xffffffff, 0xffffffff, NULL);
177 SetAPen(the_win->RPort, black_pen);
178 SetBPen(the_win->RPort, white_pen);
179 SetDrMd(the_win->RPort, JAM2);
180 return true;
181 }
182
183 // Open PIP (requires Picasso96)
184 static bool init_pip(int width, int height)
185 {
186 // Set absolute mouse mode
187 ADBSetRelMouseMode(false);
188
189 // Open window
190 ULONG error = 0;
191 the_win = p96PIP_OpenTags(
192 P96PIP_SourceFormat, RGBFB_R5G5B5,
193 P96PIP_SourceWidth, width,
194 P96PIP_SourceHeight, height,
195 P96PIP_ErrorCode, (ULONG)&error,
196 WA_Left, 0, WA_Top, 0,
197 WA_InnerWidth, width, WA_InnerHeight, height,
198 WA_SimpleRefresh, TRUE,
199 WA_NoCareRefresh, TRUE,
200 WA_Activate, TRUE,
201 WA_RMBTrap, TRUE,
202 WA_ReportMouse, TRUE,
203 WA_DragBar, TRUE,
204 WA_DepthGadget, TRUE,
205 WA_SizeGadget, FALSE,
206 WA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
207 WA_PubScreenName, (ULONG)"Workbench",
208 TAG_END
209 );
210 if (the_win == NULL || error) {
211 ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
212 return false;
213 }
214
215 // Find bitmap
216 p96PIP_GetTags(the_win, P96PIP_SourceBitMap, (ULONG)&the_bitmap, TAG_END);
217
218 // Add resolution and set VideoMonitor
219 set_video_monitor(width, height, p96GetBitMapAttr(the_bitmap, P96BMA_BYTESPERROW), 16);
220 VideoMonitor.mac_frame_base = p96GetBitMapAttr(the_bitmap, P96BMA_MEMORY);
221 return true;
222 }
223
224 // Open Picasso96 screen
225 static bool init_screen_p96(ULONG mode_id)
226 {
227 // Set relative mouse mode
228 ADBSetRelMouseMode(true);
229
230 // Check if the mode is one we can handle
231 uint32 depth = p96GetModeIDAttr(mode_id, P96IDA_DEPTH);
232 uint32 format = p96GetModeIDAttr(mode_id, P96IDA_RGBFORMAT);
233
234 switch (depth) {
235 case 8:
236 break;
237 case 15:
238 case 16:
239 if (format != RGBFB_R5G5B5) {
240 ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
241 return false;
242 }
243 break;
244 case 24:
245 case 32:
246 if (format != RGBFB_A8R8G8B8) {
247 ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
248 return false;
249 }
250 break;
251 default:
252 ErrorAlert(GetString(STR_WRONG_SCREEN_DEPTH_ERR));
253 return false;
254 }
255
256 // Yes, get width and height
257 uint32 width = p96GetModeIDAttr(mode_id, P96IDA_WIDTH);
258 uint32 height = p96GetModeIDAttr(mode_id, P96IDA_HEIGHT);
259
260 // Open screen
261 the_screen = p96OpenScreenTags(
262 P96SA_DisplayID, mode_id,
263 P96SA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
264 P96SA_Quiet, TRUE,
265 P96SA_NoMemory, TRUE,
266 P96SA_NoSprite, TRUE,
267 P96SA_Exclusive, TRUE,
268 TAG_END
269 );
270 if (the_screen == NULL) {
271 ErrorAlert(GetString(STR_OPEN_SCREEN_ERR));
272 return false;
273 }
274
275 // Open window
276 the_win = OpenWindowTags(NULL,
277 WA_Left, 0, WA_Top, 0,
278 WA_Width, width, WA_Height, height,
279 WA_NoCareRefresh, TRUE,
280 WA_Borderless, TRUE,
281 WA_Activate, TRUE,
282 WA_RMBTrap, TRUE,
283 WA_ReportMouse, TRUE,
284 WA_CustomScreen, (ULONG)the_screen,
285 TAG_END
286 );
287 if (the_win == NULL) {
288 ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
289 return false;
290 }
291
292 ScreenToFront(the_screen);
293
294 // Add resolution and set VideoMonitor
295 set_video_monitor(width, height, p96GetBitMapAttr(the_screen->RastPort.BitMap, P96BMA_BYTESPERROW), depth);
296 VideoMonitor.mac_frame_base = p96GetBitMapAttr(the_screen->RastPort.BitMap, P96BMA_MEMORY);
297 return true;
298 }
299
300 // Open CyberGraphX screen
301 static bool init_screen_cgfx(ULONG mode_id)
302 {
303 // Set relative mouse mode
304 ADBSetRelMouseMode(true);
305
306 // Check if the mode is one we can handle
307 uint32 depth = GetCyberIDAttr(CYBRIDATTR_DEPTH, mode_id);
308 uint32 format = GetCyberIDAttr(CYBRIDATTR_PIXFMT, mode_id);
309
310 switch (depth) {
311 case 8:
312 break;
313 case 15:
314 case 16:
315 // !!! PIXFMT_RGB15 is correct !!!
316 if (format != PIXFMT_RGB15) {
317 ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
318 return false;
319 }
320 break;
321 case 24:
322 case 32:
323 if (format != PIXFMT_ARGB32) {
324 ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
325 return false;
326 }
327 break;
328 default:
329 ErrorAlert(GetString(STR_WRONG_SCREEN_DEPTH_ERR));
330 return false;
331 }
332
333 // Yes, get width and height
334 uint32 width = GetCyberIDAttr(CYBRIDATTR_WIDTH, mode_id);
335 uint32 height = GetCyberIDAttr(CYBRIDATTR_HEIGHT, mode_id);
336
337 // Open screen
338 the_screen = OpenScreenTags(NULL,
339 SA_DisplayID, mode_id,
340 SA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
341 SA_Quiet, TRUE,
342 SA_Exclusive, TRUE,
343 TAG_END
344 );
345 if (the_screen == NULL) {
346 ErrorAlert(GetString(STR_OPEN_SCREEN_ERR));
347 return false;
348 }
349
350 // Open window
351 the_win = OpenWindowTags(NULL,
352 WA_Left, 0, WA_Top, 0,
353 WA_Width, width, WA_Height, height,
354 WA_NoCareRefresh, TRUE,
355 WA_Borderless, TRUE,
356 WA_Activate, TRUE,
357 WA_RMBTrap, TRUE,
358 WA_ReportMouse, TRUE,
359 WA_CustomScreen, (ULONG)the_screen,
360 TAG_END
361 );
362 if (the_win == NULL) {
363 ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
364 return false;
365 }
366
367 ScreenToFront(the_screen);
368 static UWORD ptr[] = { 0, 0, 0, 0 };
369 SetPointer(the_win, ptr, 0, 0, 0, 0); // Hide mouse pointer
370
371 // Set VideoMonitor
372 ULONG frame_base;
373 APTR handle = LockBitMapTags(the_screen->RastPort.BitMap,
374 LBMI_BASEADDRESS, (ULONG)&frame_base,
375 TAG_END
376 );
377 UnLockBitMap(handle);
378 set_video_monitor(width, height, GetCyberMapAttr(the_screen->RastPort.BitMap, CYBRMATTR_XMOD), depth);
379 VideoMonitor.mac_frame_base = frame_base;
380 return true;
381 }
382
383 bool VideoInit(bool classic)
384 {
385 // Allocate blank mouse pointer data
386 null_pointer = (UWORD *)AllocMem(12, MEMF_PUBLIC | MEMF_CHIP | MEMF_CLEAR);
387 if (null_pointer == NULL) {
388 ErrorAlert(GetString(STR_NO_MEM_ERR));
389 return false;
390 }
391
392 // Read frame skip prefs
393 frame_skip = PrefsFindInt32("frameskip");
394 if (frame_skip == 0)
395 frame_skip = 1;
396
397 // Get screen mode from preferences
398 const char *mode_str;
399 if (classic)
400 mode_str = "win/512/342";
401 else
402 mode_str = PrefsFindString("screen");
403
404 // Determine type and mode
405 display_type = DISPLAY_WINDOW;
406 int width = 512, height = 384;
407 ULONG mode_id = 0;
408 if (mode_str) {
409 if (sscanf(mode_str, "win/%d/%d", &width, &height) == 2)
410 display_type = DISPLAY_WINDOW;
411 else if (sscanf(mode_str, "pip/%d/%d", &width, &height) == 2 && P96Base)
412 display_type = DISPLAY_PIP;
413 else if (sscanf(mode_str, "scr/%08lx", &mode_id) == 1 && (CyberGfxBase || P96Base)) {
414 if (P96Base && p96GetModeIDAttr(mode_id, P96IDA_ISP96))
415 display_type = DISPLAY_SCREEN_P96;
416 else if (CyberGfxBase && IsCyberModeID(mode_id))
417 display_type = DISPLAY_SCREEN_CGFX;
418 else {
419 ErrorAlert(GetString(STR_NO_P96_MODE_ERR));
420 return false;
421 }
422 }
423 }
424
425 // Open display
426 switch (display_type) {
427 case DISPLAY_WINDOW:
428 if (!init_window(width, height))
429 return false;
430 break;
431
432 case DISPLAY_PIP:
433 if (!init_pip(width, height))
434 return false;
435 break;
436
437 case DISPLAY_SCREEN_P96:
438 if (!init_screen_p96(mode_id))
439 return false;
440 break;
441
442 case DISPLAY_SCREEN_CGFX:
443 if (!init_screen_cgfx(mode_id))
444 return false;
445 break;
446 }
447
448 // Start periodic process
449 periodic_proc = CreateNewProcTags(
450 NP_Entry, (ULONG)periodic_func,
451 NP_Name, (ULONG)"Basilisk II IDCMP Handler",
452 NP_Priority, 0,
453 TAG_END
454 );
455 if (periodic_proc == NULL) {
456 ErrorAlert(GetString(STR_NO_MEM_ERR));
457 return false;
458 }
459 return true;
460 }
461
462
463 /*
464 * Deinitialization
465 */
466
467 void VideoExit(void)
468 {
469 // Stop periodic process
470 if (periodic_proc) {
471 SetSignal(0, SIGF_SINGLE);
472 Signal(&periodic_proc->pr_Task, SIGBREAKF_CTRL_C);
473 Wait(SIGF_SINGLE);
474 }
475
476 switch (display_type) {
477
478 case DISPLAY_WINDOW:
479
480 // Window mode, free bitmap
481 if (the_bitmap) {
482 WaitBlit();
483 FreeBitMap(the_bitmap);
484 }
485
486 // Free pens and close window
487 if (the_win) {
488 ReleasePen(the_win->WScreen->ViewPort.ColorMap, black_pen);
489 ReleasePen(the_win->WScreen->ViewPort.ColorMap, white_pen);
490
491 CloseWindow(the_win);
492 }
493 break;
494
495 case DISPLAY_PIP:
496
497 // Close PIP
498 if (the_win)
499 p96PIP_Close(the_win);
500 break;
501
502 case DISPLAY_SCREEN_P96:
503
504 // Close window
505 if (the_win)
506 CloseWindow(the_win);
507
508 // Close screen
509 if (the_screen) {
510 p96CloseScreen(the_screen);
511 the_screen = NULL;
512 }
513 break;
514
515 case DISPLAY_SCREEN_CGFX:
516
517 // Close window
518 if (the_win)
519 CloseWindow(the_win);
520
521 // Close screen
522 if (the_screen) {
523 CloseScreen(the_screen);
524 the_screen = NULL;
525 }
526 break;
527 }
528
529 // Free mouse pointer
530 if (null_pointer) {
531 FreeMem(null_pointer, 12);
532 null_pointer = NULL;
533 }
534 }
535
536
537 /*
538 * Set palette
539 */
540
541 void video_set_palette(uint8 *pal)
542 {
543 if (display_type == DISPLAY_SCREEN_P96 || display_type == DISPLAY_SCREEN_CGFX) {
544
545 // Convert palette to 32 bits
546 ULONG table[2 + 256 * 3];
547 table[0] = 256 << 16;
548 table[256 * 3 + 1] = 0;
549 for (int i=0; i<256; i++) {
550 table[i*3+1] = pal[i*3] * 0x01010101;
551 table[i*3+2] = pal[i*3+1] * 0x01010101;
552 table[i*3+3] = pal[i*3+2] * 0x01010101;
553 }
554
555 // And load it
556 LoadRGB32(&the_screen->ViewPort, table);
557 }
558 }
559
560
561 /*
562 * Video message handling (not neccessary under AmigaOS, handled by periodic_func())
563 */
564
565 void VideoInterrupt(void)
566 {
567 }
568
569
570 /*
571 * Process for window refresh and message handling
572 */
573
574 static __saveds void periodic_func(void)
575 {
576 struct MsgPort *timer_port = NULL;
577 struct timerequest *timer_io = NULL;
578 struct IntuiMessage *msg;
579 ULONG win_mask = 0, timer_mask = 0;
580
581 // Create message port for window and attach it
582 struct MsgPort *win_port = CreateMsgPort();
583 if (win_port) {
584 win_mask = 1 << win_port->mp_SigBit;
585 the_win->UserPort = win_port;
586 ModifyIDCMP(the_win, IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY | ((display_type == DISPLAY_SCREEN_P96 || display_type == DISPLAY_SCREEN_CGFX) ? IDCMP_DELTAMOVE : 0));
587 }
588
589 // Start 60Hz timer for window refresh
590 if (display_type == DISPLAY_WINDOW) {
591 timer_port = CreateMsgPort();
592 if (timer_port) {
593 timer_io = (struct timerequest *)CreateIORequest(timer_port, sizeof(struct timerequest));
594 if (timer_io) {
595 if (!OpenDevice((UBYTE *)TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timer_io, 0)) {
596 timer_mask = 1 << timer_port->mp_SigBit;
597 timer_io->tr_node.io_Command = TR_ADDREQUEST;
598 timer_io->tr_time.tv_secs = 0;
599 timer_io->tr_time.tv_micro = 16667 * frame_skip;
600 SendIO((struct IORequest *)timer_io);
601 }
602 }
603 }
604 }
605
606 // Main loop
607 for (;;) {
608
609 // Wait for timer and/or window (CTRL_C is used for quitting the task)
610 ULONG sig = Wait(win_mask | timer_mask | SIGBREAKF_CTRL_C);
611
612 if (sig & SIGBREAKF_CTRL_C)
613 break;
614
615 if (sig & timer_mask) {
616
617 // Timer tick, update display
618 BltTemplate(the_bitmap->Planes[0], 0, the_bitmap->BytesPerRow, the_win->RPort,
619 the_win->BorderLeft, the_win->BorderTop, VideoMonitor.mode.x, VideoMonitor.mode.y);
620
621 // Restart timer
622 timer_io->tr_node.io_Command = TR_ADDREQUEST;
623 timer_io->tr_time.tv_secs = 0;
624 timer_io->tr_time.tv_micro = 16667 * frame_skip;
625 SendIO((struct IORequest *)timer_io);
626 }
627
628 if (sig & win_mask) {
629
630 // Handle window messages
631 while (msg = (struct IntuiMessage *)GetMsg(win_port)) {
632
633 // Get data from message and reply
634 ULONG cl = msg->Class;
635 UWORD code = msg->Code;
636 UWORD qualifier = msg->Qualifier;
637 WORD mx = msg->MouseX;
638 WORD my = msg->MouseY;
639 ReplyMsg((struct Message *)msg);
640
641 // Handle message according to class
642 switch (cl) {
643 case IDCMP_MOUSEMOVE:
644 if (display_type == DISPLAY_SCREEN_P96 || display_type == DISPLAY_SCREEN_CGFX)
645 ADBMouseMoved(mx, my);
646 else {
647 ADBMouseMoved(mx - the_win->BorderLeft, my - the_win->BorderTop);
648 if (mx < the_win->BorderLeft
649 || my < the_win->BorderTop
650 || mx >= the_win->BorderLeft + VideoMonitor.mode.x
651 || my >= the_win->BorderTop + VideoMonitor.mode.y) {
652 if (current_pointer) {
653 ClearPointer(the_win);
654 current_pointer = NULL;
655 }
656 } else {
657 if (current_pointer != null_pointer) {
658 // Hide mouse pointer inside window
659 SetPointer(the_win, null_pointer, 1, 16, 0, 0);
660 current_pointer = null_pointer;
661 }
662 }
663 }
664 break;
665
666 case IDCMP_MOUSEBUTTONS:
667 if (code == SELECTDOWN)
668 ADBMouseDown(0);
669 else if (code == SELECTUP)
670 ADBMouseUp(0);
671 else if (code == MENUDOWN)
672 ADBMouseDown(1);
673 else if (code == MENUUP)
674 ADBMouseUp(1);
675 else if (code == MIDDLEDOWN)
676 ADBMouseDown(2);
677 else if (code == MIDDLEUP)
678 ADBMouseUp(2);
679 break;
680
681 case IDCMP_RAWKEY:
682 if (qualifier & IEQUALIFIER_REPEAT) // Keyboard repeat is done by MacOS
683 break;
684 if ((qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_LSHIFT | IEQUALIFIER_CONTROL)) ==
685 (IEQUALIFIER_LALT | IEQUALIFIER_LSHIFT | IEQUALIFIER_CONTROL) && code == 0x5f) {
686 SetInterruptFlag(INTFLAG_NMI);
687 TriggerInterrupt();
688 break;
689 }
690
691 if (code & IECODE_UP_PREFIX)
692 ADBKeyUp(keycode2mac[code & 0x7f]);
693 else
694 ADBKeyDown(keycode2mac[code & 0x7f]);
695 break;
696 }
697 }
698 }
699 }
700
701 // Stop timer
702 if (timer_io) {
703 if (!CheckIO((struct IORequest *)timer_io))
704 AbortIO((struct IORequest *)timer_io);
705 WaitIO((struct IORequest *)timer_io);
706 CloseDevice((struct IORequest *)timer_io);
707 DeleteIORequest(timer_io);
708 }
709 if (timer_port)
710 DeleteMsgPort(timer_port);
711
712 // Remove port from window and delete it
713 Forbid();
714 msg = (struct IntuiMessage *)win_port->mp_MsgList.lh_Head;
715 struct Node *succ;
716 while (succ = msg->ExecMessage.mn_Node.ln_Succ) {
717 if (msg->IDCMPWindow == the_win) {
718 Remove((struct Node *)msg);
719 ReplyMsg((struct Message *)msg);
720 }
721 msg = (struct IntuiMessage *)succ;
722 }
723 the_win->UserPort = NULL;
724 ModifyIDCMP(the_win, 0);
725 Permit();
726 DeleteMsgPort(win_port);
727
728 // Main task asked for termination, send signal
729 Forbid();
730 Signal(MainTask, SIGF_SINGLE);
731 }