ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/AmigaOS/video_amiga.cpp
(Generate patch)

Comparing BasiliskII/src/AmigaOS/video_amiga.cpp (file contents):
Revision 1.5 by cebix, 2000-07-13T17:45:33Z vs.
Revision 1.24 by jlachmann, 2002-06-23T08:27:05Z

# Line 1 | Line 1
1   /*
2   *  video_amiga.cpp - Video/graphics emulation, AmigaOS specific stuff
3   *
4 < *  Basilisk II (C) 1997-2000 Christian Bauer
4 > *  Basilisk II (C) 1997-2002 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
# Line 22 | Line 22
22   #include <intuition/intuition.h>
23   #include <graphics/rastport.h>
24   #include <graphics/gfx.h>
25 < #include <cybergraphx/cybergraphics.h>
25 > #include <cybergraphics/cybergraphics.h>
26   #include <dos/dostags.h>
27   #include <devices/timer.h>
28 + #define __USE_SYSBASE
29   #include <proto/exec.h>
30   #include <proto/dos.h>
31   #include <proto/intuition.h>
32   #include <proto/graphics.h>
33   #include <proto/Picasso96.h>
34   #include <proto/cybergraphics.h>
35 + #include <inline/exec.h>
36 + #include <inline/dos.h>
37 + #include <inline/intuition.h>
38 + #include <inline/Picasso96.h>
39 + #include <inline/cybergraphics.h>
40  
41   #include "sysdeps.h"
42 + #include "cpu_emulation.h"
43   #include "main.h"
44   #include "adb.h"
45   #include "prefs.h"
# Line 43 | Line 50
50   #include "debug.h"
51  
52  
53 + // Supported video modes
54 + static vector<video_mode> VideoModes;
55 +
56   // Display types
57   enum {
58          DISPLAY_WINDOW,
59          DISPLAY_PIP,
60 <        DISPLAY_SCREEN
60 >        DISPLAY_SCREEN_P96,
61 >        DISPLAY_SCREEN_CGFX
62   };
63  
64   // Global variables
65   static int32 frame_skip;
66 < static int display_type = DISPLAY_WINDOW;               // See enum above
67 < static struct Screen *the_screen = NULL;
68 < static struct Window *the_win = NULL;
58 < static struct BitMap *the_bitmap = NULL;
59 < static LONG black_pen = -1, white_pen = -1;
60 < static struct Process *periodic_proc = NULL;    // Periodic process
61 < static bool is_cgfx = false;                                    // Flag: screen mode is a CyberGfx mode
62 < static bool is_p96 = false;                                             // Flag: screen mode is a Picasso96 mode
66 > static UWORD *null_pointer = NULL;                      // Blank mouse pointer data
67 > static UWORD *current_pointer = (UWORD *)-1;            // Currently visible mouse pointer data
68 > static struct Process *periodic_proc = NULL;            // Periodic process
69  
70 < extern struct Task *MainTask;                                   // Pointer to main task (from main_amiga.cpp)
70 > extern struct Task *MainTask;                           // Pointer to main task (from main_amiga.cpp)
71  
72  
73   // Amiga -> Mac raw keycode translation table
# Line 85 | Line 91 | static const uint8 keycode2mac[0x80] = {
91   };
92  
93  
94 < // Prototypes
95 < static void periodic_func(void);
94 > class Amiga_monitor_desc : public monitor_desc {
95 > public:
96 >        Amiga_monitor_desc(const vector<video_mode> &available_modes, video_depth default_depth, uint32 default_id, int default_display_type)
97 >                :  monitor_desc(available_modes, default_depth, default_id), display_type(default_display_type) {};
98 >        ~Amiga_monitor_desc() {};
99 >
100 >        virtual void switch_to_current_mode(void);
101 >        virtual void set_palette(uint8 *pal, int num);
102 >
103 >        bool video_open(void);
104 >        void video_close(void);
105 > public:
106 >        int display_type;               // See enum above
107 > };
108  
109  
110   /*
111 < *  Initialization
111 > *  Display "driver" classes
112   */
113  
114 < // Open window
115 < static bool init_window(int width, int height)
116 < {
117 <        // Set absolute mouse mode
118 <        ADBSetRelMouseMode(false);
114 > class driver_base {
115 > public:
116 >        driver_base(Amiga_monitor_desc &m);
117 >        virtual ~driver_base();
118 >
119 >        virtual void set_palette(uint8 *pal, int num) {};
120 >        virtual struct BitMap *get_bitmap() { return NULL; };
121 > public:
122 >        Amiga_monitor_desc &monitor;    // Associated video monitor
123 >        const video_mode &mode;         // Video mode handled by the driver
124 >        BOOL init_ok;                   // Initialization succeeded (we can't use exceptions because of -fomit-frame-pointer)
125 >        struct Window *the_win;
126 > };
127  
102        // Open window
103        the_win = OpenWindowTags(NULL,
104                WA_Left, 0, WA_Top, 0,
105                WA_InnerWidth, width, WA_InnerHeight, height,
106                WA_SimpleRefresh, TRUE,
107                WA_NoCareRefresh, TRUE,
108                WA_Activate, TRUE,
109                WA_RMBTrap, TRUE,
110                WA_ReportMouse, TRUE,
111                WA_DragBar, TRUE,
112                WA_DepthGadget, TRUE,
113                WA_SizeGadget, FALSE,
114                WA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
115                TAG_END
116        );
117        if (the_win == NULL) {
118                ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
119                return false;
120        }
128  
129 <        // Create bitmap ("height + 2" for safety)
130 <        the_bitmap = AllocBitMap(width, height + 2, 1, BMF_CLEAR, NULL);
131 <        if (the_bitmap == NULL) {
132 <                ErrorAlert(GetString(STR_NO_MEM_ERR));
133 <                return false;
134 <        }
129 > class driver_window : public driver_base {
130 > public:
131 >        driver_window(Amiga_monitor_desc &m, int width, int height);
132 >        ~driver_window();
133 >
134 >        struct BitMap *get_bitmap() { return the_bitmap; };
135 >
136 > private:
137 >        LONG black_pen, white_pen;
138 >        struct BitMap *the_bitmap;
139 > };
140  
141 <        // Set VideoMonitor
142 <        VideoMonitor.mac_frame_base = (uint32)the_bitmap->Planes[0];
143 <        VideoMonitor.bytes_per_row = the_bitmap->BytesPerRow;
144 <        VideoMonitor.x = width;
133 <        VideoMonitor.y = height;
134 <        VideoMonitor.mode = VMODE_1BIT;
141 > class driver_pip : public driver_base {
142 > public:
143 >        driver_pip(Amiga_monitor_desc &m, int width, int height);
144 >        ~driver_pip();
145  
146 <        // Set FgPen and BgPen
137 <        black_pen = ObtainBestPenA(the_win->WScreen->ViewPort.ColorMap, 0, 0, 0, NULL);
138 <        white_pen = ObtainBestPenA(the_win->WScreen->ViewPort.ColorMap, 0xffffffff, 0xffffffff, 0xffffffff, NULL);
139 <        SetAPen(the_win->RPort, black_pen);
140 <        SetBPen(the_win->RPort, white_pen);
141 <        SetDrMd(the_win->RPort, JAM2);
142 <        return true;
143 < }
146 >        struct BitMap *get_bitmap() { return the_bitmap; };
147  
148 < // Open PIP (requires Picasso96)
149 < static bool init_pip(int width, int height)
150 < {
148 <        // Set absolute mouse mode
149 <        ADBSetRelMouseMode(false);
148 > private:
149 >        struct BitMap *the_bitmap;
150 > };
151  
152 <        // Open window
153 <        ULONG error = 0;
154 <        the_win = p96PIP_OpenTags(
155 <                P96PIP_SourceFormat, RGBFB_R5G5B5,
155 <                P96PIP_SourceWidth, width,
156 <                P96PIP_SourceHeight, height,
157 <                P96PIP_ErrorCode, (ULONG)&error,
158 <                WA_Left, 0, WA_Top, 0,
159 <                WA_InnerWidth, width, WA_InnerHeight, height,
160 <                WA_SimpleRefresh, TRUE,
161 <                WA_NoCareRefresh, TRUE,
162 <                WA_Activate, TRUE,
163 <                WA_RMBTrap, TRUE,
164 <                WA_ReportMouse, TRUE,
165 <                WA_DragBar, TRUE,
166 <                WA_DepthGadget, TRUE,
167 <                WA_SizeGadget, FALSE,
168 <                WA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
169 <                WA_PubScreenName, (ULONG)"Workbench",
170 <                TAG_END
171 <        );
172 <        if (the_win == NULL || error) {
173 <                ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
174 <                return false;
175 <        }
152 > class driver_screen_p96 : public driver_base {
153 > public:
154 >        driver_screen_p96(Amiga_monitor_desc &m, ULONG mode_id);
155 >        ~driver_screen_p96();
156  
157 <        // Find bitmap
178 <        p96PIP_GetTags(the_win, P96PIP_SourceBitMap, (ULONG)&the_bitmap, TAG_END);
157 >        void set_palette(uint8 *pal, int num);
158  
159 <        // Set VideoMonitor
160 <        VideoMonitor.mac_frame_base = p96GetBitMapAttr(the_bitmap, P96BMA_MEMORY);
161 <        VideoMonitor.bytes_per_row = p96GetBitMapAttr(the_bitmap, P96BMA_BYTESPERROW);
183 <        VideoMonitor.x = width;
184 <        VideoMonitor.y = height;
185 <        VideoMonitor.mode = VMODE_16BIT;
186 <        return true;
187 < }
159 > private:
160 >        struct Screen *the_screen;
161 > };
162  
163 < // Open screen (requires Picasso96/CyberGfx as we need chunky modes)
164 < static bool init_screen(ULONG mode_id)
165 < {
166 <        // Set relative mouse mode
193 <        ADBSetRelMouseMode(true);
163 > class driver_screen_cgfx : public driver_base {
164 > public:
165 >        driver_screen_cgfx(Amiga_monitor_desc &m, ULONG mode_id);
166 >        ~driver_screen_cgfx();
167  
168 <        // Check whether the mode is a Picasso96 mode or a CyberGfx mode
196 <        if (P96Base && p96GetModeIDAttr(mode_id, P96IDA_ISP96))
197 <                is_p96 = true;
198 <        else if (CyberGfxBase && IsCyberModeID(mode_id))
199 <                is_cgfx = true;
200 <        else {
201 <                ErrorAlert(GetString(STR_NO_P96_MODE_ERR));
202 <                return false;
203 <        }
168 >        void set_palette(uint8 *pal, int num);
169  
170 <        uint32 depth;
171 <        uint32 format;
170 > private:
171 >        struct Screen *the_screen;
172 > };
173  
208        // Check if the mode is one we can handle
209        if (is_p96) {
210                depth = p96GetModeIDAttr(mode_id, P96IDA_DEPTH);
211                format = p96GetModeIDAttr(mode_id, P96IDA_RGBFORMAT);
212        } else {
213                depth = GetCyberIDAttr(CYBRIDATTR_DEPTH, mode_id);
214                format = GetCyberIDAttr(CYBRIDATTR_PIXFMT, mode_id);
215        }
174  
175 <        switch (depth) {
218 <                case 8:
219 <                        VideoMonitor.mode = VMODE_8BIT;
220 <                        break;
221 <                case 15:
222 <                case 16:
223 <                        if (format != RGBFB_R5G5B5 && format != PIXFMT_RGB16) {
224 <                                ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
225 <                                return false;
226 <                        }
227 <                        VideoMonitor.mode = VMODE_16BIT;
228 <                        break;
229 <                case 24:
230 <                case 32:
231 <                        if (format != RGBFB_A8R8G8B8 && format != PIXFMT_ARGB32) {
232 <                                ErrorAlert(GetString(STR_WRONG_SCREEN_FORMAT_ERR));
233 <                                return false;
234 <                        }
235 <                        VideoMonitor.mode = VMODE_32BIT;
236 <                        break;
237 <                default:
238 <                        ErrorAlert(GetString(STR_WRONG_SCREEN_DEPTH_ERR));
239 <                        return false;
240 <        }
175 > static driver_base *drv = NULL; // Pointer to currently used driver object
176  
242        // Yes, get width and height
243        uint32 width;
244        uint32 height;
177  
246        if (is_p96) {
247                width = p96GetModeIDAttr(mode_id, P96IDA_WIDTH);
248                height = p96GetModeIDAttr(mode_id, P96IDA_HEIGHT);
249        } else {
250                width = GetCyberIDAttr(CYBRIDATTR_WIDTH, mode_id);
251                height = GetCyberIDAttr(CYBRIDATTR_HEIGHT, mode_id);
252        }
253        VideoMonitor.x = width;
254        VideoMonitor.y = height;
178  
179 <        // Open screen
180 <        if (is_p96) {
181 <                the_screen = p96OpenScreenTags(
182 <                        P96SA_DisplayID, mode_id,
183 <                        P96SA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
184 <                        P96SA_Quiet, TRUE,
185 <                        P96SA_NoMemory, TRUE,
186 <                        P96SA_NoSprite, TRUE,
187 <                        P96SA_Exclusive, TRUE,
265 <                        TAG_END
266 <                );
267 <        } else {
268 <                the_screen = OpenScreenTags(NULL,
269 <                        SA_DisplayID, mode_id,
270 <                        SA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
271 <                        SA_Quiet, TRUE,
272 <                        SA_Exclusive, TRUE,
273 <                        TAG_END
274 <                );
275 <        }
179 > // Prototypes
180 > static void periodic_func(void);
181 > static void add_mode(uint32 width, uint32 height, uint32 resolution_id, uint32 bytes_per_row, video_depth depth);
182 > static void add_modes(uint32 width, uint32 height, video_depth depth);
183 > static ULONG find_mode_for_depth(uint32 width, uint32 height, uint32 depth);
184 > static ULONG bits_from_depth(video_depth depth);
185 > static bool is_valid_modeid(int display_type, ULONG mode_id);
186 > static bool check_modeid_p96(ULONG mode_id);
187 > static bool check_modeid_cgfx(ULONG mode_id);
188  
277        if (the_screen == NULL) {
278                ErrorAlert(GetString(STR_OPEN_SCREEN_ERR));
279                return false;
280        }
189  
190 <        // Open window
191 <        the_win = OpenWindowTags(NULL,
192 <                WA_Left, 0, WA_Top, 0,
285 <                WA_Width, width, WA_Height, height,
286 <                WA_NoCareRefresh, TRUE,
287 <                WA_Borderless, TRUE,
288 <                WA_Activate, TRUE,
289 <                WA_RMBTrap, TRUE,
290 <                WA_ReportMouse, TRUE,
291 <                WA_CustomScreen, (ULONG)the_screen,
292 <                TAG_END
293 <        );
294 <        if (the_win == NULL) {
295 <                ErrorAlert(GetString(STR_OPEN_WINDOW_ERR));
296 <                return false;
297 <        }
190 > /*
191 > *  Initialization
192 > */
193  
299        // Set VideoMonitor
300        ScreenToFront(the_screen);
301        if (is_p96) {
302                VideoMonitor.mac_frame_base = p96GetBitMapAttr(the_screen->RastPort.BitMap, P96BMA_MEMORY);
303                VideoMonitor.bytes_per_row = p96GetBitMapAttr(the_screen->RastPort.BitMap, P96BMA_BYTESPERROW);
304        } else {
305                static UWORD ptr[] = { 0, 0, 0, 0 };
306                SetPointer(the_win, ptr, 0, 0, 0, 0);   // Hide Pointer
307
308                APTR handle = LockBitMapTags(the_screen->RastPort.BitMap,
309                                LBMI_BASEADDRESS, (ULONG)&VideoMonitor.mac_frame_base,
310                                TAG_END);
311                UnLockBitMap(handle);
312                VideoMonitor.bytes_per_row = GetCyberMapAttr(the_screen->RastPort.BitMap, CYBRMATTR_XMOD);
313        }
314        return true;
315 }
194  
195   bool VideoInit(bool classic)
196   {
197 +        video_depth default_depth = VDEPTH_1BIT;
198 +        int default_width, default_height;
199 +        int default_display_type = DISPLAY_WINDOW;
200 +        int window_width, window_height;                        // width and height for window display
201 +        ULONG screen_mode_id;                           // mode ID for screen display
202 +
203 +        // Allocate blank mouse pointer data
204 +        null_pointer = (UWORD *)AllocMem(12, MEMF_PUBLIC | MEMF_CHIP | MEMF_CLEAR);
205 +        if (null_pointer == NULL) {
206 +                ErrorAlert(STR_NO_MEM_ERR);
207 +                return false;
208 +        }
209 +
210          // Read frame skip prefs
211          frame_skip = PrefsFindInt32("frameskip");
212          if (frame_skip == 0)
# Line 328 | Line 219 | bool VideoInit(bool classic)
219          else
220                  mode_str = PrefsFindString("screen");
221  
222 <        // Determine type and mode
223 <        display_type = DISPLAY_WINDOW;
224 <        int width = 512, height = 384;
334 <        ULONG mode_id = 0;
222 >        default_width = window_width = 512;
223 >        default_height = window_height = 384;
224 >
225          if (mode_str) {
226 <                if (sscanf(mode_str, "win/%d/%d", &width, &height) == 2)
227 <                        display_type = DISPLAY_WINDOW;
228 <                else if (sscanf(mode_str, "pip/%d/%d", &width, &height) == 2 && P96Base)
229 <                        display_type = DISPLAY_PIP;
230 <                else if (sscanf(mode_str, "scr/%08lx", &mode_id) == 1 && (CyberGfxBase || P96Base))
231 <                        display_type = DISPLAY_SCREEN;
226 >                if (sscanf(mode_str, "win/%d/%d", &window_width, &window_height) == 2)
227 >                        default_display_type = DISPLAY_WINDOW;
228 >                else if (sscanf(mode_str, "pip/%d/%d", &window_width, &window_height) == 2 && P96Base)
229 >                        default_display_type = DISPLAY_PIP;
230 >                else if (sscanf(mode_str, "scr/%08lx", &screen_mode_id) == 1 && (CyberGfxBase || P96Base)) {
231 >                        if (P96Base && p96GetModeIDAttr(screen_mode_id, P96IDA_ISP96))
232 >                                default_display_type = DISPLAY_SCREEN_P96;
233 >                        else if (CyberGfxBase && IsCyberModeID(screen_mode_id))
234 >                                default_display_type = DISPLAY_SCREEN_CGFX;
235 >                        else {
236 >                                ErrorAlert(STR_NO_P96_MODE_ERR);
237 >                                return false;
238 >                        }
239 >                }
240 >        }
241 >
242 >        D(bug("default_display_type %d, window_width %d, window_height %d\n", default_display_type, window_width, window_height));
243 >
244 >        // Construct list of supported modes
245 >        switch (default_display_type) {
246 >                case DISPLAY_WINDOW:
247 >                        default_width = window_width;
248 >                        default_height = window_height;
249 >                        default_depth = VDEPTH_1BIT;
250 >                        add_modes(window_width, window_height, VDEPTH_1BIT);
251 >                        break;
252 >
253 >                case DISPLAY_PIP:
254 >                        default_depth = VDEPTH_16BIT;
255 >                        default_width = window_width;
256 >                        default_height = window_height;
257 >                        add_modes(window_width, window_height, VDEPTH_16BIT);
258 >                        break;
259 >
260 >                case DISPLAY_SCREEN_P96:
261 >                case DISPLAY_SCREEN_CGFX:
262 >                        struct DimensionInfo dimInfo;
263 >                        DisplayInfoHandle handle = FindDisplayInfo(screen_mode_id);
264 >
265 >                        if (handle == NULL)
266 >                                return false;
267 >
268 >                        if (GetDisplayInfoData(handle, (UBYTE *) &dimInfo, sizeof(dimInfo), DTAG_DIMS, 0) <= 0)
269 >                                return false;
270 >
271 >                        default_width = 1 + dimInfo.Nominal.MaxX - dimInfo.Nominal.MinX;
272 >                        default_height = 1 + dimInfo.Nominal.MaxY - dimInfo.Nominal.MinY;
273 >
274 >                        switch (dimInfo.MaxDepth)
275 >                                {
276 >                        case 1:
277 >                                default_depth = VDEPTH_1BIT;
278 >                                break;
279 >                        case 8:
280 >                                default_depth = VDEPTH_8BIT;
281 >                                break;
282 >                        case 15:
283 >                        case 16:
284 >                                default_depth = VDEPTH_16BIT;
285 >                                break;
286 >                        case 24:
287 >                        case 32:
288 >                                default_depth = VDEPTH_32BIT;
289 >                                break;
290 >                                }
291 >
292 >                        for (unsigned d=VDEPTH_8BIT; d<=VDEPTH_32BIT; d++) {
293 >                                ULONG mode_id = find_mode_for_depth(default_width, default_height, bits_from_depth(video_depth(d)));
294 >
295 >                                if (is_valid_modeid(default_display_type, mode_id))
296 >                                        add_modes(default_width, default_height, video_depth(d));
297 >                        }
298 >                        break;
299 >        }
300 >
301 > //      video_init_depth_list();
302 >
303 > #if DEBUG
304 >        bug("Available video modes:\n");
305 >        vector<video_mode>::const_iterator i = VideoModes.begin(), end = VideoModes.end();
306 >        while (i != end) {
307 >                bug(" %ld x %ld (ID %02lx), %ld colors\n", i->x, i->y, i->resolution_id, 1 << bits_from_depth(i->depth));
308 >                ++i;
309 >        }
310 > #endif
311 >
312 >        D(bug("VideoInit/%ld: def_width=%ld  def_height=%ld  def_depth=%ld\n", \
313 >                __LINE__, default_width, default_height, default_depth));
314 >
315 >        // Find requested default mode and open display
316 >        if (VideoModes.size() == 1)
317 >                {
318 >                uint32 default_id ;
319 >
320 >                // Create Amiga_monitor_desc for this (the only) display
321 >                default_id = VideoModes[0].resolution_id;
322 >                D(bug("VideoInit/%ld: default_id=%ld\n", __LINE__, default_id));
323 >                Amiga_monitor_desc *monitor = new Amiga_monitor_desc(VideoModes, default_depth, default_id, default_display_type);
324 >                VideoMonitors.push_back(monitor);
325 >
326 >                // Open display
327 >                return monitor->video_open();
328 >                }
329 >        else {
330 >                // Find mode with specified dimensions
331 >                std::vector<video_mode>::const_iterator i, end = VideoModes.end();
332 >                for (i = VideoModes.begin(); i != end; ++i) {
333 >                        D(bug("VideoInit/%ld: w=%ld  h=%ld  d=%ld\n", __LINE__, i->x, i->y, bits_from_depth(i->depth)));
334 >                        if (i->x == default_width && i->y == default_height && i->depth == default_depth)
335 >                                {
336 >                                // Create Amiga_monitor_desc for this (the only) display
337 >                                uint32 default_id = i->resolution_id;
338 >                                D(bug("VideoInit/%ld: default_id=%ld\n", __LINE__, default_id));
339 >                                Amiga_monitor_desc *monitor = new Amiga_monitor_desc(VideoModes, default_depth, default_id, default_display_type);
340 >                                VideoMonitors.push_back(monitor);
341 >
342 >                                // Open display
343 >                                return monitor->video_open();
344 >                                }
345 >                }
346 >
347 >                // Create Amiga_monitor_desc for this (the only) display
348 >                uint32 default_id = VideoModes[0].resolution_id;
349 >                D(bug("VideoInit/%ld: default_id=%ld\n", __LINE__, default_id));
350 >                Amiga_monitor_desc *monitor = new Amiga_monitor_desc(VideoModes, default_depth, default_id, default_display_type);
351 >                VideoMonitors.push_back(monitor);
352 >
353 >                // Open display
354 >                return monitor->video_open();
355          }
356  
357 +        return true;
358 + }
359 +
360 +
361 + bool Amiga_monitor_desc::video_open()
362 + {
363 +        const video_mode &mode = get_current_mode();
364 +        ULONG depth_bits = bits_from_depth(mode.depth);
365 +        ULONG ID = find_mode_for_depth(mode.x, mode.y, depth_bits);
366 +
367 +        D(bug("video_open/%ld: width=%ld  height=%ld  depth=%ld  ID=%08lx\n", __LINE__, mode.x, mode.y, depth_bits, ID));
368 +
369 +        if (ID == INVALID_ID) {
370 +                ErrorAlert(STR_NO_VIDEO_MODE_ERR);
371 +                return false;
372 +        }
373 +
374 + //      VideoMonitor.mode = mode;
375 +
376 +        D(bug("video_open/%ld: display_type=%ld\n", __LINE__, display_type));
377 +
378          // Open display
379          switch (display_type) {
380                  case DISPLAY_WINDOW:
381 <                        if (!init_window(width, height))
348 <                                return false;
381 >                        drv = new driver_window(*this, mode.x, mode.y);
382                          break;
383  
384                  case DISPLAY_PIP:
385 <                        if (!init_pip(width, height))
353 <                                return false;
385 >                        drv = new driver_pip(*this, mode.x, mode.y);
386                          break;
387  
388 <                case DISPLAY_SCREEN:
389 <                        if (!init_screen(mode_id))
390 <                                return false;
388 >                case DISPLAY_SCREEN_P96:
389 >                        drv = new driver_screen_p96(*this, ID);
390 >                        break;
391 >
392 >                case DISPLAY_SCREEN_CGFX:
393 >                        drv = new driver_screen_cgfx(*this, ID);
394                          break;
395          }
396  
397 +        D(bug("video_open/%ld: drv=%08lx\n", __LINE__, drv));
398 +
399 +        if (drv == NULL)
400 +                return false;
401 +
402 +        D(bug("video_open/%ld: init_ok=%ld\n", __LINE__, drv->init_ok));
403 +        if (!drv->init_ok) {
404 +                delete drv;
405 +                drv = NULL;
406 +                return false;
407 +        }
408 +
409          // Start periodic process
410          periodic_proc = CreateNewProcTags(
411                  NP_Entry, (ULONG)periodic_func,
# Line 366 | Line 413 | bool VideoInit(bool classic)
413                  NP_Priority, 0,
414                  TAG_END
415          );
416 +
417 +        D(bug("video_open/%ld: periodic_proc=%08lx\n", __LINE__, periodic_proc));
418 +
419          if (periodic_proc == NULL) {
420 <                ErrorAlert(GetString(STR_NO_MEM_ERR));
420 >                ErrorAlert(STR_NO_MEM_ERR);
421                  return false;
422          }
423 +
424          return true;
425   }
426  
427  
428 < /*
378 < *  Deinitialization
379 < */
380 <
381 < void VideoExit(void)
428 > void Amiga_monitor_desc::video_close()
429   {
430          // Stop periodic process
431          if (periodic_proc) {
# Line 387 | Line 434 | void VideoExit(void)
434                  Wait(SIGF_SINGLE);
435          }
436  
437 <        switch (display_type) {
437 >        delete drv;
438  
439 <                case DISPLAY_WINDOW:
439 >        // Free mouse pointer
440 >        if (null_pointer) {
441 >                FreeMem(null_pointer, 12);
442 >                null_pointer = NULL;
443 >        }
444 > }
445  
394                        // Window mode, free bitmap
395                        if (the_bitmap) {
396                                WaitBlit();
397                                FreeBitMap(the_bitmap);
398                        }
446  
447 <                        // Free pens and close window
448 <                        if (the_win) {
449 <                                ReleasePen(the_win->WScreen->ViewPort.ColorMap, black_pen);
403 <                                ReleasePen(the_win->WScreen->ViewPort.ColorMap, white_pen);
447 > /*
448 > *  Deinitialization
449 > */
450  
451 <                                CloseWindow(the_win);
452 <                        }
453 <                        break;
451 > void VideoExit(void)
452 > {
453 >        // Close displays
454 >        vector<monitor_desc *>::iterator i, end = VideoMonitors.end();
455 >        for (i = VideoMonitors.begin(); i != end; ++i)
456 >                dynamic_cast<Amiga_monitor_desc *>(*i)->video_close();
457 > }
458  
409                case DISPLAY_PIP:
459  
460 <                        // Close PIP
461 <                        if (the_win)
462 <                                p96PIP_Close(the_win);
414 <                        break;
460 > /*
461 > *  Set palette
462 > */
463  
464 <                case DISPLAY_SCREEN:
464 > void Amiga_monitor_desc::set_palette(uint8 *pal, int num)
465 > {
466 >        drv->set_palette(pal, num);
467 > }
468  
418                        // Close window
419                        if (the_win)
420                                CloseWindow(the_win);
469  
470 <                        // Close screen
471 <                        if (the_screen) {
472 <                                if (is_p96)
425 <                                        p96CloseScreen(the_screen);
426 <                                else
427 <                                        CloseScreen(the_screen);
470 > /*
471 > *  Switch video mode
472 > */
473  
474 <                                the_screen = NULL;
475 <                        }
476 <                        break;
474 > void Amiga_monitor_desc::switch_to_current_mode()
475 > {
476 >        // Close and reopen display
477 >        video_close();
478 >        if (!video_open()) {
479 >                ErrorAlert(STR_OPEN_WINDOW_ERR);
480 >                QuitEmulator();
481          }
482   }
483  
484  
485   /*
486 < *  Set palette
486 > *  Close down full-screen mode (if bringing up error alerts is unsafe while in full-screen mode)
487   */
488  
489 < void video_set_palette(uint8 *pal)
489 > void VideoQuitFullScreen(void)
490   {
442        if (display_type == DISPLAY_SCREEN) {
443
444                // Convert palette to 32 bits
445                ULONG table[2 + 256 * 3];
446                table[0] = 256 << 16;
447                table[256 * 3 + 1] = 0;
448                for (int i=0; i<256; i++) {
449                        table[i*3+1] = pal[i*3] * 0x01010101;
450                        table[i*3+2] = pal[i*3+1] * 0x01010101;
451                        table[i*3+3] = pal[i*3+2] * 0x01010101;
452                }
453
454                // And load it
455                LoadRGB32(&the_screen->ViewPort, table);
456        }
491   }
492  
493  
# Line 477 | Line 511 | static __saveds void periodic_func(void)
511          struct IntuiMessage *msg;
512          ULONG win_mask = 0, timer_mask = 0;
513  
514 +        D(bug("periodic_func/%ld: \n", __LINE__));
515 +
516          // Create message port for window and attach it
517          struct MsgPort *win_port = CreateMsgPort();
518          if (win_port) {
519                  win_mask = 1 << win_port->mp_SigBit;
520 <                the_win->UserPort = win_port;
521 <                ModifyIDCMP(the_win, IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY | (display_type == DISPLAY_SCREEN ? IDCMP_DELTAMOVE : 0));
520 >                drv->the_win->UserPort = win_port;
521 >                ModifyIDCMP(drv->the_win, IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_RAWKEY |
522 >                        ((drv->monitor.display_type == DISPLAY_SCREEN_P96 || drv->monitor.display_type == DISPLAY_SCREEN_CGFX) ? IDCMP_DELTAMOVE : 0));
523          }
524  
525 +        D(bug("periodic_func/%ld: \n", __LINE__));
526 +
527          // Start 60Hz timer for window refresh
528 <        if (display_type == DISPLAY_WINDOW) {
528 >        if (drv->monitor.display_type == DISPLAY_WINDOW) {
529                  timer_port = CreateMsgPort();
530                  if (timer_port) {
531                          timer_io = (struct timerequest *)CreateIORequest(timer_port, sizeof(struct timerequest));
532                          if (timer_io) {
533 <                                if (!OpenDevice((UBYTE *)TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timer_io, 0)) {
533 >                                if (!OpenDevice((UBYTE *) TIMERNAME, UNIT_MICROHZ, (struct IORequest *)timer_io, 0)) {
534                                          timer_mask = 1 << timer_port->mp_SigBit;
535                                          timer_io->tr_node.io_Command = TR_ADDREQUEST;
536                                          timer_io->tr_time.tv_secs = 0;
# Line 502 | Line 541 | static __saveds void periodic_func(void)
541                  }
542          }
543  
544 +        D(bug("periodic_func/%ld: \n", __LINE__));
545 +
546          // Main loop
547          for (;;) {
548 +                const video_mode &mode = drv->monitor.get_current_mode();
549  
550                  // Wait for timer and/or window (CTRL_C is used for quitting the task)
551                  ULONG sig = Wait(win_mask | timer_mask | SIGBREAKF_CTRL_C);
# Line 511 | Line 553 | static __saveds void periodic_func(void)
553                  if (sig & SIGBREAKF_CTRL_C)
554                          break;
555  
556 <                if (sig & timer_mask) {
556 > //              D(bug("periodic_func/%ld: display_type=%ld  the_win=%08lx\n", __LINE__, drv->monitor.display_type, drv->the_win));
557  
558 <                        // Timer tick, update display
559 <                        BltTemplate(the_bitmap->Planes[0], 0, the_bitmap->BytesPerRow, the_win->RPort,
560 <                                the_win->BorderLeft, the_win->BorderTop, VideoMonitor.x, VideoMonitor.y);
558 >                if (sig & timer_mask) {
559 >                        if (drv->get_bitmap())
560 >                                {
561 >                                // Timer tick, update display
562 >                                BltTemplate(drv->get_bitmap()->Planes[0], 0,
563 >                                        drv->get_bitmap()->BytesPerRow, drv->the_win->RPort,
564 >                                        drv->the_win->BorderLeft, drv->the_win->BorderTop,
565 >                                        mode.x, mode.y);
566 >                                }
567  
568                          // Restart timer
569                          timer_io->tr_node.io_Command = TR_ADDREQUEST;
# Line 540 | Line 588 | static __saveds void periodic_func(void)
588                                  // Handle message according to class
589                                  switch (cl) {
590                                          case IDCMP_MOUSEMOVE:
591 <                                                if (display_type == DISPLAY_SCREEN)
591 >                                                switch (drv->monitor.display_type)
592 >                                                        {
593 >                                                case DISPLAY_SCREEN_P96:
594 >                                                case DISPLAY_SCREEN_CGFX:
595 > //                                                      D(bug("periodic_func/%ld: IDCMP_MOUSEMOVE mx=%ld  my=%ld\n", __LINE__, mx, my));
596                                                          ADBMouseMoved(mx, my);
597 <                                                else
598 <                                                        ADBMouseMoved(mx - the_win->BorderLeft, my - the_win->BorderTop);
597 >                                                        break;
598 >                                                default:
599 > //                                                      D(bug("periodic_func/%ld: IDCMP_MOUSEMOVE mx=%ld  my=%ld\n", __LINE__, mx - drv->the_win->BorderLeft, my - drv->the_win->BorderTop));
600 >                                                        ADBMouseMoved(mx - drv->the_win->BorderLeft, my - drv->the_win->BorderTop);
601 >                                                        if (mx < drv->the_win->BorderLeft
602 >                                                         || my < drv->the_win->BorderTop
603 >                                                         || mx >= drv->the_win->BorderLeft + mode.x
604 >                                                         || my >= drv->the_win->BorderTop + mode.y) {
605 >                                                                if (current_pointer) {
606 >                                                                        ClearPointer(drv->the_win);
607 >                                                                        current_pointer = NULL;
608 >                                                                }
609 >                                                        } else {
610 >                                                                if (current_pointer != null_pointer) {
611 >                                                                        // Hide mouse pointer inside window
612 >                                                                        SetPointer(drv->the_win, null_pointer, 1, 16, 0, 0);
613 >                                                                        current_pointer = null_pointer;
614 >                                                                }
615 >                                                        }
616 >                                                        break;
617 >                                                        }
618                                                  break;
619  
620                                          case IDCMP_MOUSEBUTTONS:
# Line 564 | Line 635 | static __saveds void periodic_func(void)
635                                          case IDCMP_RAWKEY:
636                                                  if (qualifier & IEQUALIFIER_REPEAT)     // Keyboard repeat is done by MacOS
637                                                          break;
638 +                                                if ((qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_LSHIFT | IEQUALIFIER_CONTROL)) ==
639 +                                                    (IEQUALIFIER_LALT | IEQUALIFIER_LSHIFT | IEQUALIFIER_CONTROL) && code == 0x5f) {
640 +                                                        SetInterruptFlag(INTFLAG_NMI);
641 +                                                        TriggerInterrupt();
642 +                                                        break;
643 +                                                }
644 +
645                                                  if (code & IECODE_UP_PREFIX)
646                                                          ADBKeyUp(keycode2mac[code & 0x7f]);
647                                                  else
# Line 574 | Line 652 | static __saveds void periodic_func(void)
652                  }
653          }
654  
655 +        D(bug("periodic_func/%ld: \n", __LINE__));
656 +
657          // Stop timer
658          if (timer_io) {
659                  if (!CheckIO((struct IORequest *)timer_io))
# Line 590 | Line 670 | static __saveds void periodic_func(void)
670          msg = (struct IntuiMessage *)win_port->mp_MsgList.lh_Head;
671          struct Node *succ;
672          while (succ = msg->ExecMessage.mn_Node.ln_Succ) {
673 <                if (msg->IDCMPWindow == the_win) {
673 >                if (msg->IDCMPWindow == drv->the_win) {
674                          Remove((struct Node *)msg);
675                          ReplyMsg((struct Message *)msg);
676                  }
677                  msg = (struct IntuiMessage *)succ;
678          }
679 <        the_win->UserPort = NULL;
680 <        ModifyIDCMP(the_win, 0);
679 >        drv->the_win->UserPort = NULL;
680 >        ModifyIDCMP(drv->the_win, 0);
681          Permit();
682          DeleteMsgPort(win_port);
683  
# Line 605 | Line 685 | static __saveds void periodic_func(void)
685          Forbid();
686          Signal(MainTask, SIGF_SINGLE);
687   }
688 +
689 +
690 + // Add mode to list of supported modes
691 + static void add_mode(uint32 width, uint32 height, uint32 resolution_id, uint32 bytes_per_row, video_depth depth)
692 + {
693 +        video_mode mode;
694 +        mode.x = width;
695 +        mode.y = height;
696 +        mode.resolution_id = resolution_id;
697 +        mode.bytes_per_row = bytes_per_row;
698 +        mode.depth = depth;
699 +
700 +        D(bug("Added video mode: w=%ld  h=%ld  d=%ld\n", width, height, depth));
701 +
702 +        VideoModes.push_back(mode);
703 + }
704 +
705 + // Add standard list of modes for given color depth
706 + static void add_modes(uint32 width, uint32 height, video_depth depth)
707 + {
708 +        D(bug("add_modes: w=%ld  h=%ld  d=%ld\n", width, height, depth));
709 +
710 +        if (width >= 512 && height >= 384)
711 +                add_mode(512, 384, 0x80, TrivialBytesPerRow(512, depth), depth);
712 +        if (width >= 640 && height >= 480)
713 +                add_mode(640, 480, 0x81, TrivialBytesPerRow(640, depth), depth);
714 +        if (width >= 800 && height >= 600)
715 +                add_mode(800, 600, 0x82, TrivialBytesPerRow(800, depth), depth);
716 +        if (width >= 1024 && height >= 768)
717 +                add_mode(1024, 768, 0x83, TrivialBytesPerRow(1024, depth), depth);
718 +        if (width >= 1152 && height >= 870)
719 +                add_mode(1152, 870, 0x84, TrivialBytesPerRow(1152, depth), depth);
720 +        if (width >= 1280 && height >= 1024)
721 +                add_mode(1280, 1024, 0x85, TrivialBytesPerRow(1280, depth), depth);
722 +        if (width >= 1600 && height >= 1200)
723 +                add_mode(1600, 1200, 0x86, TrivialBytesPerRow(1600, depth), depth);
724 + }
725 +
726 +
727 + static ULONG find_mode_for_depth(uint32 width, uint32 height, uint32 depth)
728 + {
729 +        ULONG ID = BestModeID(BIDTAG_NominalWidth, width,
730 +                BIDTAG_NominalHeight, height,
731 +                BIDTAG_Depth, depth,
732 +                BIDTAG_DIPFMustNotHave, DIPF_IS_ECS | DIPF_IS_HAM | DIPF_IS_AA,
733 +                TAG_END);
734 +
735 +        return ID;
736 + }
737 +
738 +
739 + static ULONG bits_from_depth(video_depth depth)
740 + {
741 +        int bits = 1 << depth;
742 +        if (bits == 16)
743 +                bits = 15;
744 +        else if (bits == 32)
745 +                bits = 24;
746 +
747 +        return bits;
748 + }
749 +
750 +
751 + static bool is_valid_modeid(int display_type, ULONG mode_id)
752 + {
753 +        if (INVALID_ID == mode_id)
754 +                return false;
755 +
756 +        switch (display_type) {
757 +                case DISPLAY_SCREEN_P96:
758 +                        return check_modeid_p96(mode_id);
759 +                        break;
760 +                case DISPLAY_SCREEN_CGFX:
761 +                        return check_modeid_cgfx(mode_id);
762 +                        break;
763 +                default:
764 +                        return false;
765 +                        break;
766 +        }
767 + }
768 +
769 +
770 + static bool check_modeid_p96(ULONG mode_id)
771 + {
772 +        // Check if the mode is one we can handle
773 +        uint32 depth = p96GetModeIDAttr(mode_id, P96IDA_DEPTH);
774 +        uint32 format = p96GetModeIDAttr(mode_id, P96IDA_RGBFORMAT);
775 +
776 +        D(bug("check_modeid_p96: mode_id=%08lx  depth=%ld  format=%ld\n", mode_id, depth, format));
777 +
778 +        if (!p96GetModeIDAttr(mode_id, P96IDA_ISP96))
779 +                return false;
780 +
781 +        switch (depth) {
782 +                case 8:
783 +                        break;
784 +                case 15:
785 +                case 16:
786 +                        if (format != RGBFB_R5G5B5)
787 +                                return false;
788 +                        break;
789 +                case 24:
790 +                case 32:
791 +                        if (format != RGBFB_A8R8G8B8)
792 +                                return false;
793 +                        break;
794 +                default:
795 +                        return false;
796 +        }
797 +
798 +        return true;
799 + }
800 +
801 +
802 + static bool check_modeid_cgfx(ULONG mode_id)
803 + {
804 +        uint32 depth = GetCyberIDAttr(CYBRIDATTR_DEPTH, mode_id);
805 +        uint32 format = GetCyberIDAttr(CYBRIDATTR_PIXFMT, mode_id);
806 +
807 +        D(bug("check_modeid_cgfx: mode_id=%08lx  depth=%ld  format=%ld\n", mode_id, depth, format));
808 +
809 +        if (!IsCyberModeID(mode_id))
810 +                return false;
811 +
812 +        switch (depth) {
813 +                case 8:
814 +                        break;
815 +                case 15:
816 +                case 16:
817 +                        if (format != PIXFMT_RGB15)
818 +                                return false;
819 +                        break;
820 +                case 24:
821 +                case 32:
822 +                        if (format != PIXFMT_ARGB32)
823 +                                return false;
824 +                        break;
825 +                default:
826 +                        return false;
827 +        }
828 +
829 +        return true;
830 + }
831 +
832 +
833 + driver_base::driver_base(Amiga_monitor_desc &m)
834 + : monitor(m), mode(m.get_current_mode()), init_ok(false)
835 + {
836 + }
837 +
838 + driver_base::~driver_base()
839 + {
840 + }
841 +
842 +
843 + // Open window
844 + driver_window::driver_window(Amiga_monitor_desc &m, int width, int height)
845 +        : black_pen(-1), white_pen(-1), driver_base(m)
846 + {
847 +        // Set relative mouse mode
848 +        ADBSetRelMouseMode(false);
849 +
850 +        // Open window
851 +        the_win = OpenWindowTags(NULL,
852 +                WA_Left, 0, WA_Top, 0,
853 +                WA_InnerWidth, width, WA_InnerHeight, height,
854 +                WA_SimpleRefresh, true,
855 +                WA_NoCareRefresh, true,
856 +                WA_Activate, true,
857 +                WA_RMBTrap, true,
858 +                WA_ReportMouse, true,
859 +                WA_DragBar, true,
860 +                WA_DepthGadget, true,
861 +                WA_SizeGadget, false,
862 +                WA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
863 +                TAG_END
864 +        );
865 +        if (the_win == NULL) {
866 +                init_ok = false;
867 +                ErrorAlert(STR_OPEN_WINDOW_ERR);
868 +                return;
869 +        }
870 +
871 +        // Create bitmap ("height + 2" for safety)
872 +        the_bitmap = AllocBitMap(width, height + 2, 1, BMF_CLEAR, NULL);
873 +        if (the_bitmap == NULL) {
874 +                init_ok = false;
875 +                ErrorAlert(STR_NO_MEM_ERR);
876 +                return;
877 +        }
878 +
879 +        // Add resolution and set VideoMonitor
880 +        monitor.set_mac_frame_base((uint32)the_bitmap->Planes[0]);
881 +
882 +        // Set FgPen and BgPen
883 +        black_pen = ObtainBestPenA(the_win->WScreen->ViewPort.ColorMap, 0, 0, 0, NULL);
884 +        white_pen = ObtainBestPenA(the_win->WScreen->ViewPort.ColorMap, 0xffffffff, 0xffffffff, 0xffffffff, NULL);
885 +        SetAPen(the_win->RPort, black_pen);
886 +        SetBPen(the_win->RPort, white_pen);
887 +        SetDrMd(the_win->RPort, JAM2);
888 +
889 +        init_ok = true;
890 + }
891 +
892 +
893 + driver_window::~driver_window()
894 + {
895 +        // Window mode, free bitmap
896 +        if (the_bitmap) {
897 +                WaitBlit();
898 +                FreeBitMap(the_bitmap);
899 +        }
900 +
901 +        // Free pens and close window
902 +        if (the_win) {
903 +                ReleasePen(the_win->WScreen->ViewPort.ColorMap, black_pen);
904 +                ReleasePen(the_win->WScreen->ViewPort.ColorMap, white_pen);
905 +
906 +                CloseWindow(the_win);
907 +                the_win = NULL;
908 +        }
909 + }
910 +
911 +
912 + // Open PIP (requires Picasso96)
913 + driver_pip::driver_pip(Amiga_monitor_desc &m, int width, int height)
914 +        : driver_base(m)
915 + {
916 +        // Set relative mouse mode
917 +        ADBSetRelMouseMode(false);
918 +
919 +        // Open window
920 +        ULONG error = 0;
921 +        the_win = p96PIP_OpenTags(
922 +                P96PIP_SourceFormat, RGBFB_R5G5B5,
923 +                P96PIP_SourceWidth, width,
924 +                P96PIP_SourceHeight, height,
925 +                P96PIP_ErrorCode, (ULONG)&error,
926 +                WA_Left, 0, WA_Top, 0,
927 +                WA_InnerWidth, width, WA_InnerHeight, height,
928 +                WA_SimpleRefresh, true,
929 +                WA_NoCareRefresh, true,
930 +                WA_Activate, true,
931 +                WA_RMBTrap, true,
932 +                WA_ReportMouse, true,
933 +                WA_DragBar, true,
934 +                WA_DepthGadget, true,
935 +                WA_SizeGadget, false,
936 +                WA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
937 +                WA_PubScreenName, (ULONG)"Workbench",
938 +                TAG_END
939 +        );
940 +        if (the_win == NULL || error) {
941 +                init_ok = false;
942 +                ErrorAlert(STR_OPEN_WINDOW_ERR);
943 +                return;
944 +        }
945 +
946 +        // Find bitmap
947 +        p96PIP_GetTags(the_win, P96PIP_SourceBitMap, (ULONG)&the_bitmap, TAG_END);
948 +
949 +        // Add resolution and set VideoMonitor
950 +        monitor.set_mac_frame_base(p96GetBitMapAttr(the_bitmap, P96BMA_MEMORY));
951 +
952 +        init_ok = true;
953 + }
954 +
955 + driver_pip::~driver_pip()
956 + {
957 +        // Close PIP
958 +        if (the_win)
959 +                p96PIP_Close(the_win);
960 + }
961 +
962 +
963 + // Open Picasso96 screen
964 + driver_screen_p96::driver_screen_p96(Amiga_monitor_desc &m, ULONG mode_id)
965 +        : driver_base(m)
966 + {
967 +        // Set absolute mouse mode
968 +        ADBSetRelMouseMode(true);
969 +
970 +        // Check if the mode is one we can handle
971 +        if (!check_modeid_p96(mode_id))
972 +                {
973 +                init_ok = false;
974 +                ErrorAlert(STR_WRONG_SCREEN_FORMAT_ERR);
975 +                return;
976 +                }
977 +
978 +        // Yes, get width and height
979 +        uint32 depth = p96GetModeIDAttr(mode_id, P96IDA_DEPTH);
980 +        uint32 width = p96GetModeIDAttr(mode_id, P96IDA_WIDTH);
981 +        uint32 height = p96GetModeIDAttr(mode_id, P96IDA_HEIGHT);
982 +
983 +        // Open screen
984 +        the_screen = p96OpenScreenTags(
985 +                P96SA_DisplayID, mode_id,
986 +                P96SA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
987 +                P96SA_Quiet, true,
988 +                P96SA_NoMemory, true,
989 +                P96SA_NoSprite, true,
990 +                P96SA_Exclusive, true,
991 +                TAG_END
992 +        );
993 +        if (the_screen == NULL) {
994 +                ErrorAlert(STR_OPEN_SCREEN_ERR);
995 +                init_ok = false;
996 +                return;
997 +        }
998 +
999 +        // Open window
1000 +        the_win = OpenWindowTags(NULL,
1001 +                WA_Left, 0, WA_Top, 0,
1002 +                WA_Width, width, WA_Height, height,
1003 +                WA_SimpleRefresh, true,
1004 +                WA_NoCareRefresh, true,
1005 +                WA_Borderless, true,
1006 +                WA_Activate, true,
1007 +                WA_RMBTrap, true,
1008 +                WA_ReportMouse, true,
1009 +                WA_CustomScreen, (ULONG)the_screen,
1010 +                TAG_END
1011 +        );
1012 +        if (the_win == NULL) {
1013 +                ErrorAlert(STR_OPEN_WINDOW_ERR);
1014 +                init_ok = false;
1015 +                return;
1016 +        }
1017 +
1018 +        ScreenToFront(the_screen);
1019 +
1020 +        // Add resolution and set VideoMonitor
1021 +        monitor.set_mac_frame_base(p96GetBitMapAttr(the_screen->RastPort.BitMap, P96BMA_MEMORY));
1022 +
1023 +        init_ok = true;
1024 + }
1025 +
1026 +
1027 + driver_screen_p96::~driver_screen_p96()
1028 + {
1029 +        // Close window
1030 +        if (the_win)
1031 +                {
1032 +                CloseWindow(the_win);
1033 +                the_win = NULL;
1034 +                }
1035 +
1036 +        // Close screen
1037 +        if (the_screen) {
1038 +                p96CloseScreen(the_screen);
1039 +                the_screen = NULL;
1040 +        }
1041 + }
1042 +
1043 +
1044 + void driver_screen_p96::set_palette(uint8 *pal, int num)
1045 + {
1046 +        // Convert palette to 32 bits
1047 +        ULONG table[2 + 256 * 3];
1048 +        table[0] = num << 16;
1049 +        table[num * 3 + 1] = 0;
1050 +        for (int i=0; i<num; i++) {
1051 +                table[i*3+1] = pal[i*3] * 0x01010101;
1052 +                table[i*3+2] = pal[i*3+1] * 0x01010101;
1053 +                table[i*3+3] = pal[i*3+2] * 0x01010101;
1054 +        }
1055 +
1056 +        // And load it
1057 +        LoadRGB32(&the_screen->ViewPort, table);
1058 + }
1059 +
1060 +
1061 + // Open CyberGraphX screen
1062 + driver_screen_cgfx::driver_screen_cgfx(Amiga_monitor_desc &m, ULONG mode_id)
1063 +        : driver_base(m)
1064 + {
1065 +        D(bug("driver_screen_cgfx/%ld: mode_id=%08lx\n", __LINE__, mode_id));
1066 +
1067 +        // Set absolute mouse mode
1068 +        ADBSetRelMouseMode(true);
1069 +
1070 +        // Check if the mode is one we can handle
1071 +        if (!check_modeid_cgfx(mode_id))
1072 +                {
1073 +                ErrorAlert(STR_WRONG_SCREEN_FORMAT_ERR);
1074 +                init_ok = false;
1075 +                return;
1076 +                }
1077 +
1078 +        // Yes, get width and height
1079 +        uint32 depth = GetCyberIDAttr(CYBRIDATTR_DEPTH, mode_id);
1080 +        uint32 width = GetCyberIDAttr(CYBRIDATTR_WIDTH, mode_id);
1081 +        uint32 height = GetCyberIDAttr(CYBRIDATTR_HEIGHT, mode_id);
1082 +
1083 +        // Open screen
1084 +        the_screen = OpenScreenTags(NULL,
1085 +                SA_DisplayID, mode_id,
1086 +                SA_Title, (ULONG)GetString(STR_WINDOW_TITLE),
1087 +                SA_Quiet, true,
1088 +                SA_Exclusive, true,
1089 +                TAG_END
1090 +        );
1091 +        if (the_screen == NULL) {
1092 +                ErrorAlert(STR_OPEN_SCREEN_ERR);
1093 +                init_ok = false;
1094 +                return;
1095 +        }
1096 +
1097 +        // Open window
1098 +        the_win = OpenWindowTags(NULL,
1099 +                WA_Left, 0, WA_Top, 0,
1100 +                WA_Width, width, WA_Height, height,
1101 +                WA_SimpleRefresh, true,
1102 +                WA_NoCareRefresh, true,
1103 +                WA_Borderless, true,
1104 +                WA_Activate, true,
1105 +                WA_RMBTrap, true,
1106 +                WA_ReportMouse, true,
1107 +                WA_CustomScreen, (ULONG)the_screen,
1108 +                TAG_END
1109 +        );
1110 +        if (the_win == NULL) {
1111 +                ErrorAlert(STR_OPEN_WINDOW_ERR);
1112 +                init_ok = false;
1113 +                return;
1114 +        }
1115 +
1116 +        ScreenToFront(the_screen);
1117 +        static UWORD ptr[] = { 0, 0, 0, 0 };
1118 +        SetPointer(the_win, ptr, 0, 0, 0, 0);   // Hide mouse pointer
1119 +
1120 +        // Set VideoMonitor
1121 +        ULONG frame_base;
1122 +        APTR handle = LockBitMapTags(the_screen->RastPort.BitMap,
1123 +                LBMI_BASEADDRESS, (ULONG)&frame_base,
1124 +                TAG_END
1125 +        );
1126 +        UnLockBitMap(handle);
1127 +
1128 +        D(bug("driver_screen_cgfx/%ld: frame_base=%08lx\n", __LINE__, frame_base));
1129 +
1130 +        monitor.set_mac_frame_base(frame_base);
1131 +
1132 +        init_ok = true;
1133 + }
1134 +
1135 +
1136 + driver_screen_cgfx::~driver_screen_cgfx()
1137 + {
1138 +        D(bug("~driver_screen_cgfx/%ld: \n", __LINE__));
1139 +
1140 +        // Close window
1141 +        if (the_win)
1142 +                {
1143 +                CloseWindow(the_win);
1144 +                the_win = NULL;
1145 +                }
1146 +
1147 +        // Close screen
1148 +        if (the_screen) {
1149 +                CloseScreen(the_screen);
1150 +                the_screen = NULL;
1151 +        }
1152 + }
1153 +
1154 +
1155 + void driver_screen_cgfx::set_palette(uint8 *pal, int num)
1156 + {
1157 +        // Convert palette to 32 bits
1158 +        ULONG table[2 + 256 * 3];
1159 +        table[0] = num << 16;
1160 +        table[num * 3 + 1] = 0;
1161 +        for (int i=0; i<num; i++) {
1162 +                table[i*3+1] = pal[i*3] * 0x01010101;
1163 +                table[i*3+2] = pal[i*3+1] * 0x01010101;
1164 +                table[i*3+3] = pal[i*3+2] * 0x01010101;
1165 +        }
1166 +
1167 +        // And load it
1168 +        LoadRGB32(&the_screen->ViewPort, table);
1169 + }
1170 +

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines