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.8 by cebix, 2000-07-22T18:25:48Z vs.
Revision 1.28 by gbeauche, 2008-01-01T09:40:31Z

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines