ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/AmigaOS/video_amiga.cpp
Revision: 1.10
Committed: 2000-09-04T16:30:48Z (24 years, 3 months ago) by cebix
Branch: MAIN
Changes since 1.9: +4 -5 lines
Log Message:
- some cleanups in the AmigaOS code

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * video_amiga.cpp - Video/graphics emulation, AmigaOS specific stuff
3     *
4 cebix 1.3 * Basilisk II (C) 1997-2000 Christian Bauer
5 cebix 1.1 *
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 cebix 1.7 #include <cybergraphics/cybergraphics.h>
26 cebix 1.1 #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 cebix 1.4 #include <proto/cybergraphics.h>
34 cebix 1.1
35     #include "sysdeps.h"
36 jlachmann 1.9 #include "cpu_emulation.h"
37 cebix 1.1 #include "main.h"
38     #include "adb.h"
39     #include "prefs.h"
40     #include "user_strings.h"
41     #include "video.h"
42    
43 cebix 1.4 #define DEBUG 0
44 cebix 1.1 #include "debug.h"
45    
46    
47     // Display types
48     enum {
49     DISPLAY_WINDOW,
50     DISPLAY_PIP,
51 cebix 1.6 DISPLAY_SCREEN_P96,
52     DISPLAY_SCREEN_CGFX
53 cebix 1.1 };
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 cebix 1.8 static UWORD *null_pointer = NULL; // Blank mouse pointer data
62     static UWORD *current_pointer = (UWORD *)-1; // Currently visible mouse pointer data
63 cebix 1.1 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     // Open window
99     static bool init_window(int width, int height)
100     {
101     // Set absolute mouse mode
102     ADBSetRelMouseMode(false);
103    
104     // Open window
105     the_win = OpenWindowTags(NULL,
106     WA_Left, 0, WA_Top, 0,
107     WA_InnerWidth, width, WA_InnerHeight, height,
108     WA_SimpleRefresh, TRUE,
109     WA_NoCareRefresh, TRUE,
110     WA_Activate, TRUE,
111     WA_RMBTrap, TRUE,
112     WA_ReportMouse, TRUE,
113     WA_DragBar, TRUE,
114     WA_DepthGadget, TRUE,
115     WA_SizeGadget, FALSE,
116 cebix 1.2 WA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
117 cebix 1.1 TAG_END
118     );
119     if (the_win == NULL) {
120     ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
121     return false;
122     }
123    
124     // Create bitmap ("height + 2" for safety)
125     the_bitmap = AllocBitMap(width, height + 2, 1, BMF_CLEAR, NULL);
126     if (the_bitmap == NULL) {
127     ErrorAlert(GetString(STR_NO_MEM_ERR));
128     return false;
129     }
130    
131     // Set VideoMonitor
132     VideoMonitor.mac_frame_base = (uint32)the_bitmap->Planes[0];
133     VideoMonitor.bytes_per_row = the_bitmap->BytesPerRow;
134     VideoMonitor.x = width;
135     VideoMonitor.y = height;
136     VideoMonitor.mode = VMODE_1BIT;
137    
138     // Set FgPen and BgPen
139     black_pen = ObtainBestPenA(the_win->WScreen->ViewPort.ColorMap, 0, 0, 0, NULL);
140     white_pen = ObtainBestPenA(the_win->WScreen->ViewPort.ColorMap, 0xffffffff, 0xffffffff, 0xffffffff, NULL);
141     SetAPen(the_win->RPort, black_pen);
142     SetBPen(the_win->RPort, white_pen);
143     SetDrMd(the_win->RPort, JAM2);
144     return true;
145     }
146    
147     // Open PIP (requires Picasso96)
148     static bool init_pip(int width, int height)
149     {
150     // Set absolute mouse mode
151     ADBSetRelMouseMode(false);
152    
153     // Open window
154     ULONG error = 0;
155     the_win = p96PIP_OpenTags(
156     P96PIP_SourceFormat, RGBFB_R5G5B5,
157     P96PIP_SourceWidth, width,
158     P96PIP_SourceHeight, height,
159 cebix 1.2 P96PIP_ErrorCode, (ULONG)&error,
160 cebix 1.1 WA_Left, 0, WA_Top, 0,
161     WA_InnerWidth, width, WA_InnerHeight, height,
162     WA_SimpleRefresh, TRUE,
163     WA_NoCareRefresh, TRUE,
164     WA_Activate, TRUE,
165     WA_RMBTrap, TRUE,
166     WA_ReportMouse, TRUE,
167     WA_DragBar, TRUE,
168     WA_DepthGadget, TRUE,
169     WA_SizeGadget, FALSE,
170 cebix 1.2 WA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
171     WA_PubScreenName, (ULONG)"Workbench",
172 cebix 1.1 TAG_END
173     );
174     if (the_win == NULL || error) {
175     ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
176     return false;
177     }
178    
179     // Find bitmap
180 cebix 1.2 p96PIP_GetTags(the_win, P96PIP_SourceBitMap, (ULONG)&the_bitmap, TAG_END);
181 cebix 1.1
182     // Set VideoMonitor
183     VideoMonitor.mac_frame_base = p96GetBitMapAttr(the_bitmap, P96BMA_MEMORY);
184     VideoMonitor.bytes_per_row = p96GetBitMapAttr(the_bitmap, P96BMA_BYTESPERROW);
185     VideoMonitor.x = width;
186     VideoMonitor.y = height;
187     VideoMonitor.mode = VMODE_16BIT;
188     return true;
189     }
190    
191 cebix 1.6 // Open Picasso96 screen
192     static bool init_screen_p96(ULONG mode_id)
193 cebix 1.1 {
194     // Set relative mouse mode
195     ADBSetRelMouseMode(true);
196    
197 cebix 1.6 // Check if the mode is one we can handle
198     uint32 depth = p96GetModeIDAttr(mode_id, P96IDA_DEPTH);
199     uint32 format = p96GetModeIDAttr(mode_id, P96IDA_RGBFORMAT);
200    
201     switch (depth) {
202     case 8:
203     VideoMonitor.mode = VMODE_8BIT;
204     break;
205     case 15:
206     case 16:
207     if (format != RGBFB_R5G5B5) {
208     ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
209     return false;
210     }
211     VideoMonitor.mode = VMODE_16BIT;
212     break;
213     case 24:
214     case 32:
215     if (format != RGBFB_A8R8G8B8) {
216     ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
217     return false;
218     }
219     VideoMonitor.mode = VMODE_32BIT;
220     break;
221     default:
222     ErrorAlert(GetString(STR_WRONG_SCREEN_DEPTH_ERR));
223     return false;
224     }
225    
226     // Yes, get width and height
227     uint32 width = p96GetModeIDAttr(mode_id, P96IDA_WIDTH);
228     uint32 height = p96GetModeIDAttr(mode_id, P96IDA_HEIGHT);
229    
230     VideoMonitor.x = width;
231     VideoMonitor.y = height;
232    
233     // Open screen
234     the_screen = p96OpenScreenTags(
235     P96SA_DisplayID, mode_id,
236     P96SA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
237     P96SA_Quiet, TRUE,
238     P96SA_NoMemory, TRUE,
239     P96SA_NoSprite, TRUE,
240     P96SA_Exclusive, TRUE,
241     TAG_END
242     );
243     if (the_screen == NULL) {
244     ErrorAlert(GetString(STR_OPEN_SCREEN_ERR));
245 cebix 1.1 return false;
246     }
247    
248 cebix 1.6 // Open window
249     the_win = OpenWindowTags(NULL,
250     WA_Left, 0, WA_Top, 0,
251     WA_Width, width, WA_Height, height,
252     WA_NoCareRefresh, TRUE,
253     WA_Borderless, TRUE,
254     WA_Activate, TRUE,
255     WA_RMBTrap, TRUE,
256     WA_ReportMouse, TRUE,
257     WA_CustomScreen, (ULONG)the_screen,
258     TAG_END
259     );
260     if (the_win == NULL) {
261     ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
262     return false;
263     }
264    
265     // Set VideoMonitor
266     ScreenToFront(the_screen);
267     VideoMonitor.mac_frame_base = p96GetBitMapAttr(the_screen->RastPort.BitMap, P96BMA_MEMORY);
268     VideoMonitor.bytes_per_row = p96GetBitMapAttr(the_screen->RastPort.BitMap, P96BMA_BYTESPERROW);
269     return true;
270     }
271    
272     // Open CyberGraphX screen
273     static bool init_screen_cgfx(ULONG mode_id)
274     {
275     // Set relative mouse mode
276     ADBSetRelMouseMode(true);
277 cebix 1.4
278 cebix 1.1 // Check if the mode is one we can handle
279 cebix 1.6 uint32 depth = GetCyberIDAttr(CYBRIDATTR_DEPTH, mode_id);
280     uint32 format = GetCyberIDAttr(CYBRIDATTR_PIXFMT, mode_id);
281 cebix 1.4
282 cebix 1.1 switch (depth) {
283     case 8:
284     VideoMonitor.mode = VMODE_8BIT;
285     break;
286     case 15:
287     case 16:
288 jlachmann 1.9 // !!! PIXFMT_RGB15 is correct !!!
289     if (format != PIXFMT_RGB15) {
290 cebix 1.1 ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
291     return false;
292     }
293     VideoMonitor.mode = VMODE_16BIT;
294     break;
295     case 24:
296     case 32:
297 cebix 1.6 if (format != PIXFMT_ARGB32) {
298 cebix 1.1 ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
299     return false;
300     }
301     VideoMonitor.mode = VMODE_32BIT;
302     break;
303     default:
304     ErrorAlert(GetString(STR_WRONG_SCREEN_DEPTH_ERR));
305     return false;
306     }
307    
308     // Yes, get width and height
309 cebix 1.6 uint32 width = GetCyberIDAttr(CYBRIDATTR_WIDTH, mode_id);
310     uint32 height = GetCyberIDAttr(CYBRIDATTR_HEIGHT, mode_id);
311 cebix 1.4
312 cebix 1.1 VideoMonitor.x = width;
313     VideoMonitor.y = height;
314    
315     // Open screen
316 cebix 1.6 the_screen = OpenScreenTags(NULL,
317     SA_DisplayID, mode_id,
318     SA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
319     SA_Quiet, TRUE,
320     SA_Exclusive, TRUE,
321     TAG_END
322     );
323 cebix 1.1 if (the_screen == NULL) {
324     ErrorAlert(GetString(STR_OPEN_SCREEN_ERR));
325     return false;
326     }
327    
328     // Open window
329     the_win = OpenWindowTags(NULL,
330     WA_Left, 0, WA_Top, 0,
331     WA_Width, width, WA_Height, height,
332     WA_NoCareRefresh, TRUE,
333     WA_Borderless, TRUE,
334     WA_Activate, TRUE,
335     WA_RMBTrap, TRUE,
336     WA_ReportMouse, TRUE,
337 cebix 1.2 WA_CustomScreen, (ULONG)the_screen,
338 cebix 1.1 TAG_END
339     );
340     if (the_win == NULL) {
341     ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
342     return false;
343     }
344    
345     // Set VideoMonitor
346     ScreenToFront(the_screen);
347 cebix 1.6 static UWORD ptr[] = { 0, 0, 0, 0 };
348     SetPointer(the_win, ptr, 0, 0, 0, 0); // Hide mouse pointer
349     APTR handle = LockBitMapTags(the_screen->RastPort.BitMap,
350     LBMI_BASEADDRESS, (ULONG)&VideoMonitor.mac_frame_base,
351     TAG_END);
352     UnLockBitMap(handle);
353     VideoMonitor.bytes_per_row = GetCyberMapAttr(the_screen->RastPort.BitMap, CYBRMATTR_XMOD);
354 cebix 1.1 return true;
355     }
356    
357     bool VideoInit(bool classic)
358     {
359 cebix 1.8 // Allocate blank mouse pointer data
360     null_pointer = (UWORD *)AllocMem(12, MEMF_PUBLIC | MEMF_CHIP | MEMF_CLEAR);
361     if (null_pointer == NULL) {
362     ErrorAlert(GetString(STR_NO_MEM_ERR));
363     return false;
364     }
365    
366 cebix 1.1 // Read frame skip prefs
367     frame_skip = PrefsFindInt32("frameskip");
368     if (frame_skip == 0)
369     frame_skip = 1;
370    
371     // Get screen mode from preferences
372     const char *mode_str;
373     if (classic)
374     mode_str = "win/512/342";
375     else
376     mode_str = PrefsFindString("screen");
377    
378     // Determine type and mode
379     display_type = DISPLAY_WINDOW;
380     int width = 512, height = 384;
381     ULONG mode_id = 0;
382     if (mode_str) {
383     if (sscanf(mode_str, "win/%d/%d", &width, &height) == 2)
384     display_type = DISPLAY_WINDOW;
385     else if (sscanf(mode_str, "pip/%d/%d", &width, &height) == 2 && P96Base)
386     display_type = DISPLAY_PIP;
387 cebix 1.6 else if (sscanf(mode_str, "scr/%08lx", &mode_id) == 1 && (CyberGfxBase || P96Base)) {
388     if (P96Base && p96GetModeIDAttr(mode_id, P96IDA_ISP96))
389     display_type = DISPLAY_SCREEN_P96;
390     else if (CyberGfxBase && IsCyberModeID(mode_id))
391     display_type = DISPLAY_SCREEN_CGFX;
392     else {
393     ErrorAlert(GetString(STR_NO_P96_MODE_ERR));
394     return false;
395     }
396     }
397 cebix 1.1 }
398    
399     // Open display
400     switch (display_type) {
401     case DISPLAY_WINDOW:
402     if (!init_window(width, height))
403     return false;
404     break;
405    
406     case DISPLAY_PIP:
407     if (!init_pip(width, height))
408     return false;
409     break;
410    
411 cebix 1.6 case DISPLAY_SCREEN_P96:
412     if (!init_screen_p96(mode_id))
413     return false;
414     break;
415    
416     case DISPLAY_SCREEN_CGFX:
417     if (!init_screen_cgfx(mode_id))
418 cebix 1.1 return false;
419     break;
420     }
421    
422     // Start periodic process
423     periodic_proc = CreateNewProcTags(
424 cebix 1.2 NP_Entry, (ULONG)periodic_func,
425     NP_Name, (ULONG)"Basilisk II IDCMP Handler",
426 cebix 1.1 NP_Priority, 0,
427     TAG_END
428     );
429     if (periodic_proc == NULL) {
430     ErrorAlert(GetString(STR_NO_MEM_ERR));
431     return false;
432     }
433     return true;
434     }
435    
436    
437     /*
438     * Deinitialization
439     */
440    
441     void VideoExit(void)
442     {
443     // Stop periodic process
444     if (periodic_proc) {
445     SetSignal(0, SIGF_SINGLE);
446     Signal(&periodic_proc->pr_Task, SIGBREAKF_CTRL_C);
447     Wait(SIGF_SINGLE);
448     }
449    
450     switch (display_type) {
451    
452     case DISPLAY_WINDOW:
453    
454     // Window mode, free bitmap
455     if (the_bitmap) {
456     WaitBlit();
457     FreeBitMap(the_bitmap);
458     }
459    
460     // Free pens and close window
461     if (the_win) {
462     ReleasePen(the_win->WScreen->ViewPort.ColorMap, black_pen);
463     ReleasePen(the_win->WScreen->ViewPort.ColorMap, white_pen);
464    
465     CloseWindow(the_win);
466     }
467     break;
468    
469     case DISPLAY_PIP:
470    
471     // Close PIP
472     if (the_win)
473     p96PIP_Close(the_win);
474     break;
475    
476 cebix 1.6 case DISPLAY_SCREEN_P96:
477 cebix 1.1
478     // Close window
479     if (the_win)
480     CloseWindow(the_win);
481    
482     // Close screen
483 cebix 1.4 if (the_screen) {
484 cebix 1.6 p96CloseScreen(the_screen);
485     the_screen = NULL;
486     }
487     break;
488    
489     case DISPLAY_SCREEN_CGFX:
490    
491     // Close window
492     if (the_win)
493     CloseWindow(the_win);
494 cebix 1.4
495 cebix 1.6 // Close screen
496     if (the_screen) {
497     CloseScreen(the_screen);
498 cebix 1.4 the_screen = NULL;
499     }
500 cebix 1.1 break;
501     }
502 cebix 1.8
503     // Free mouse pointer
504     if (null_pointer) {
505     FreeMem(null_pointer, 12);
506     null_pointer = NULL;
507     }
508 cebix 1.1 }
509    
510    
511     /*
512     * Set palette
513     */
514    
515     void video_set_palette(uint8 *pal)
516     {
517 cebix 1.6 if (display_type == DISPLAY_SCREEN_P96 || display_type == DISPLAY_SCREEN_CGFX) {
518 cebix 1.1
519     // Convert palette to 32 bits
520     ULONG table[2 + 256 * 3];
521     table[0] = 256 << 16;
522     table[256 * 3 + 1] = 0;
523     for (int i=0; i<256; i++) {
524     table[i*3+1] = pal[i*3] * 0x01010101;
525     table[i*3+2] = pal[i*3+1] * 0x01010101;
526     table[i*3+3] = pal[i*3+2] * 0x01010101;
527     }
528    
529     // And load it
530     LoadRGB32(&the_screen->ViewPort, table);
531     }
532     }
533    
534    
535     /*
536     * Video message handling (not neccessary under AmigaOS, handled by periodic_func())
537     */
538    
539     void VideoInterrupt(void)
540     {
541     }
542    
543    
544     /*
545     * Process for window refresh and message handling
546     */
547    
548     static __saveds void periodic_func(void)
549     {
550     struct MsgPort *timer_port = NULL;
551     struct timerequest *timer_io = NULL;
552     struct IntuiMessage *msg;
553     ULONG win_mask = 0, timer_mask = 0;
554    
555     // Create message port for window and attach it
556     struct MsgPort *win_port = CreateMsgPort();
557     if (win_port) {
558     win_mask = 1 << win_port->mp_SigBit;
559     the_win->UserPort = win_port;
560 cebix 1.6 ModifyIDCMP(the_win, IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY | ((display_type == DISPLAY_SCREEN_P96 || display_type == DISPLAY_SCREEN_CGFX) ? IDCMP_DELTAMOVE : 0));
561 cebix 1.1 }
562    
563     // Start 60Hz timer for window refresh
564     if (display_type == DISPLAY_WINDOW) {
565     timer_port = CreateMsgPort();
566     if (timer_port) {
567     timer_io = (struct timerequest *)CreateIORequest(timer_port, sizeof(struct timerequest));
568     if (timer_io) {
569     if (!OpenDevice((UBYTE *)TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timer_io, 0)) {
570     timer_mask = 1 << timer_port->mp_SigBit;
571     timer_io->tr_node.io_Command = TR_ADDREQUEST;
572     timer_io->tr_time.tv_secs = 0;
573     timer_io->tr_time.tv_micro = 16667 * frame_skip;
574     SendIO((struct IORequest *)timer_io);
575     }
576     }
577     }
578     }
579    
580     // Main loop
581     for (;;) {
582    
583     // Wait for timer and/or window (CTRL_C is used for quitting the task)
584     ULONG sig = Wait(win_mask | timer_mask | SIGBREAKF_CTRL_C);
585    
586     if (sig & SIGBREAKF_CTRL_C)
587     break;
588    
589     if (sig & timer_mask) {
590    
591     // Timer tick, update display
592     BltTemplate(the_bitmap->Planes[0], 0, the_bitmap->BytesPerRow, the_win->RPort,
593     the_win->BorderLeft, the_win->BorderTop, VideoMonitor.x, VideoMonitor.y);
594    
595     // Restart timer
596     timer_io->tr_node.io_Command = TR_ADDREQUEST;
597     timer_io->tr_time.tv_secs = 0;
598     timer_io->tr_time.tv_micro = 16667 * frame_skip;
599     SendIO((struct IORequest *)timer_io);
600     }
601    
602     if (sig & win_mask) {
603    
604     // Handle window messages
605     while (msg = (struct IntuiMessage *)GetMsg(win_port)) {
606    
607     // Get data from message and reply
608     ULONG cl = msg->Class;
609     UWORD code = msg->Code;
610     UWORD qualifier = msg->Qualifier;
611     WORD mx = msg->MouseX;
612     WORD my = msg->MouseY;
613     ReplyMsg((struct Message *)msg);
614    
615     // Handle message according to class
616     switch (cl) {
617     case IDCMP_MOUSEMOVE:
618 cebix 1.7 if (display_type == DISPLAY_SCREEN_P96 || display_type == DISPLAY_SCREEN_CGFX)
619 cebix 1.1 ADBMouseMoved(mx, my);
620 cebix 1.8 else {
621 cebix 1.1 ADBMouseMoved(mx - the_win->BorderLeft, my - the_win->BorderTop);
622 cebix 1.8 if (mx < the_win->BorderLeft
623     || my < the_win->BorderTop
624     || mx >= the_win->BorderLeft + VideoMonitor.x
625     || my >= the_win->BorderTop + VideoMonitor.y) {
626     if (current_pointer) {
627     ClearPointer(the_win);
628     current_pointer = NULL;
629     }
630     } else {
631     if (current_pointer != null_pointer) {
632     // Hide mouse pointer inside window
633     SetPointer(the_win, null_pointer, 1, 16, 0, 0);
634     current_pointer = null_pointer;
635     }
636     }
637     }
638 cebix 1.1 break;
639    
640     case IDCMP_MOUSEBUTTONS:
641     if (code == SELECTDOWN)
642     ADBMouseDown(0);
643     else if (code == SELECTUP)
644     ADBMouseUp(0);
645     else if (code == MENUDOWN)
646     ADBMouseDown(1);
647     else if (code == MENUUP)
648     ADBMouseUp(1);
649     else if (code == MIDDLEDOWN)
650     ADBMouseDown(2);
651     else if (code == MIDDLEUP)
652     ADBMouseUp(2);
653     break;
654    
655     case IDCMP_RAWKEY:
656     if (qualifier & IEQUALIFIER_REPEAT) // Keyboard repeat is done by MacOS
657     break;
658 cebix 1.10 if ((qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_LSHIFT | IEQUALIFIER_CONTROL)) ==
659     (IEQUALIFIER_LALT | IEQUALIFIER_LSHIFT | IEQUALIFIER_CONTROL))
660     && code == 0x5f) {
661 jlachmann 1.9 SetInterruptFlag(INTFLAG_NMI);
662     TriggerInterrupt();
663     break;
664 cebix 1.10 }
665 jlachmann 1.9
666 cebix 1.1 if (code & IECODE_UP_PREFIX)
667     ADBKeyUp(keycode2mac[code & 0x7f]);
668     else
669     ADBKeyDown(keycode2mac[code & 0x7f]);
670     break;
671     }
672     }
673     }
674     }
675    
676     // Stop timer
677     if (timer_io) {
678     if (!CheckIO((struct IORequest *)timer_io))
679     AbortIO((struct IORequest *)timer_io);
680     WaitIO((struct IORequest *)timer_io);
681     CloseDevice((struct IORequest *)timer_io);
682     DeleteIORequest(timer_io);
683     }
684     if (timer_port)
685     DeleteMsgPort(timer_port);
686    
687     // Remove port from window and delete it
688     Forbid();
689     msg = (struct IntuiMessage *)win_port->mp_MsgList.lh_Head;
690     struct Node *succ;
691     while (succ = msg->ExecMessage.mn_Node.ln_Succ) {
692     if (msg->IDCMPWindow == the_win) {
693     Remove((struct Node *)msg);
694     ReplyMsg((struct Message *)msg);
695     }
696     msg = (struct IntuiMessage *)succ;
697     }
698     the_win->UserPort = NULL;
699     ModifyIDCMP(the_win, 0);
700     Permit();
701     DeleteMsgPort(win_port);
702    
703     // Main task asked for termination, send signal
704     Forbid();
705     Signal(MainTask, SIGF_SINGLE);
706     }