ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/video.cpp
Revision: 1.11
Committed: 2001-06-28T21:19:59Z (22 years, 11 months ago) by cebix
Branch: MAIN
Changes since 1.10: +192 -65 lines
Log Message:
video_x.cpp supports resolution switching in windowed mode: the available
resolutions are 512x384, 640x480, 800x600, 1024x768 and 1280x1024 (the prefs
editor has to be updated to reflect this). The resolution selected in the
prefs editor is used as the default, but it can be changed in the Monitors
control panel. So far only tested with direct addressing.

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * video.cpp - Video/graphics emulation
3     *
4 cebix 1.7 * Basilisk II (C) 1997-2001 Christian Bauer
5 cebix 1.1 * Portions (C) 1997-1999 Marc Hellwig
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20     */
21    
22     /*
23     * SEE ALSO
24     * Inside Macintosh: Devices, chapter 1 "Device Manager"
25     * Designing Cards and Drivers for the Macintosh Family, Second Edition
26     */
27    
28     #include <stdio.h>
29    
30     #include "sysdeps.h"
31     #include "cpu_emulation.h"
32     #include "main.h"
33     #include "macos_util.h"
34     #include "video.h"
35     #include "video_defs.h"
36    
37 cebix 1.11 #define DEBUG 0
38 cebix 1.1 #include "debug.h"
39    
40    
41 cebix 1.9 // List of supported video modes
42     vector<video_mode> VideoModes;
43    
44 cebix 1.1 // Description of the main monitor
45 cebix 1.9 monitor_desc VideoMonitor;
46 cebix 1.1
47     // Local variables (per monitor)
48     struct {
49 cebix 1.9 monitor_desc *desc; // Pointer to description of monitor handled by this instance of the driver
50 cebix 1.1 uint8 palette[256 * 3]; // Color palette, 256 entries, RGB
51     bool luminance_mapping; // Luminance mapping on/off
52     bool interrupts_enabled; // VBL interrupts on/off
53 cebix 1.11 uint32 gamma_table; // Mac address of gamma table
54 cebix 1.9 uint16 current_mode; // Currently selected depth/resolution
55     uint32 current_id;
56     uint16 preferred_mode; // Preferred depth/resolution
57     uint32 preferred_id;
58 cebix 1.11 uint32 sp; // Mac address of Slot Manager parameter block
59 cebix 1.1 } VidLocal;
60    
61    
62     /*
63 cebix 1.9 * Check whether specified resolution ID is one of the supported resolutions
64     */
65    
66     static bool has_resolution(uint32 id)
67     {
68 cebix 1.10 std::vector<video_mode>::const_iterator i = VideoModes.begin(), end = VideoModes.end();
69 cebix 1.9 while (i != end) {
70     if (i->resolution_id == id)
71     return true;
72     ++i;
73     }
74     return false;
75     }
76    
77    
78     /*
79 cebix 1.10 * Find specified mode (depth/resolution) (or VideoModes.end() if not found)
80     */
81    
82     static std::vector<video_mode>::const_iterator find_mode(uint16 mode, uint32 id)
83     {
84     std::vector<video_mode>::const_iterator i = VideoModes.begin(), end = VideoModes.end();
85     while (i != end) {
86     if (i->resolution_id == id && DepthToAppleMode(i->depth) == mode)
87     return i;
88     ++i;
89     }
90     return i;
91     }
92    
93    
94     /*
95 cebix 1.9 * Find maximum supported depth for given resolution ID
96     */
97    
98     static video_depth max_depth_of_resolution(uint32 id)
99     {
100     video_depth m = VDEPTH_1BIT;
101     vector<video_mode>::const_iterator i = VideoModes.begin(), end = VideoModes.end();
102     while (i != end) {
103     if (i->depth > m)
104     m = i->depth;
105     ++i;
106     }
107     return m;
108     }
109    
110    
111     /*
112     * Get X/Y size of specified resolution
113     */
114    
115     static void get_size_of_resolution(uint32 id, uint32 &x, uint32 &y)
116     {
117     vector<video_mode>::const_iterator i = VideoModes.begin(), end = VideoModes.end();
118     while (i != end) {
119     if (i->resolution_id == id) {
120     x = i->x;
121     y = i->y;
122     return;
123     }
124     ++i;
125     }
126     }
127    
128    
129     /*
130 cebix 1.11 * Set palette to 50% gray
131     */
132    
133     static void set_gray_palette(void)
134     {
135     if (!IsDirectMode(VidLocal.current_mode)) {
136     for (int i=0; i<256; i++) {
137     VidLocal.palette[i * 3 + 0] = 127;
138     VidLocal.palette[i * 3 + 1] = 127;
139     VidLocal.palette[i * 3 + 2] = 127;
140     }
141     video_set_palette(VidLocal.palette);
142     }
143     }
144    
145    
146     /*
147 cebix 1.1 * Driver Open() routine
148     */
149    
150 cebix 1.2 int16 VideoDriverOpen(uint32 pb, uint32 dce)
151 cebix 1.1 {
152 cebix 1.2 D(bug("VideoDriverOpen\n"));
153 cebix 1.1
154 cebix 1.9 // This shouldn't happen unless the platform-specific video code is broken
155     if (VideoModes.empty())
156     fprintf(stderr, "No valid video modes found (broken video driver?)\n");
157    
158 cebix 1.1 // Init local variables
159     VidLocal.desc = &VideoMonitor;
160     VidLocal.luminance_mapping = false;
161     VidLocal.interrupts_enabled = false;
162 cebix 1.9 VidLocal.current_mode = DepthToAppleMode(VidLocal.desc->mode.depth);
163     VidLocal.current_id = VidLocal.desc->mode.resolution_id;
164     VidLocal.preferred_mode = VidLocal.current_mode;
165     VidLocal.preferred_id = VidLocal.current_id;
166 cebix 1.1
167 cebix 1.11 // Allocate Slot Manager parameter block in Mac RAM
168     M68kRegisters r;
169     r.d[0] = SIZEOF_SPBlock;
170     Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
171     if (r.a[0] == 0)
172     return memFullErr;
173     VidLocal.sp = r.a[0];
174     D(bug("SPBlock at %08x\n", VidLocal.sp));
175    
176     // Find and set default gamma table
177     VidLocal.gamma_table = 0; //!!
178    
179 cebix 1.1 // Init color palette (solid gray)
180 cebix 1.11 set_gray_palette();
181 cebix 1.1 return noErr;
182     }
183    
184    
185     /*
186     * Driver Control() routine
187     */
188    
189 cebix 1.2 int16 VideoDriverControl(uint32 pb, uint32 dce)
190 cebix 1.1 {
191     uint16 code = ReadMacInt16(pb + csCode);
192     uint32 param = ReadMacInt32(pb + csParam);
193 cebix 1.2 D(bug("VideoDriverControl %d\n", code));
194 cebix 1.1 switch (code) {
195    
196 cebix 1.9 case cscSetMode: { // Set color depth
197     uint16 mode = ReadMacInt16(param + csMode);
198     D(bug(" SetMode %04x\n", mode));
199 cebix 1.10
200 cebix 1.11 // Set old base address in case the switch fails
201     WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base);
202    
203     if (ReadMacInt16(param + csPage))
204     return paramErr;
205    
206 cebix 1.10 if (mode != VidLocal.current_mode) {
207     std::vector<video_mode>::const_iterator i = find_mode(mode, VidLocal.current_id);
208 cebix 1.11 if (i == VideoModes.end())
209 cebix 1.10 return paramErr;
210 cebix 1.11 set_gray_palette();
211 cebix 1.10 video_switch_to_mode(*i);
212     VidLocal.current_mode = mode;
213 cebix 1.11 WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base);
214     WriteMacInt32(dce + dCtlDevBase, VidLocal.desc->mac_frame_base);
215 cebix 1.10 }
216 cebix 1.11 D(bug(" base %08x\n", VidLocal.desc->mac_frame_base));
217 cebix 1.10 return noErr;
218 cebix 1.9 }
219 cebix 1.1
220     case cscSetEntries: { // Set palette
221 cebix 1.11 D(bug(" SetEntries table %08x, count %d, start %d\n", ReadMacInt32(param + csTable), ReadMacInt16(param + csCount), ReadMacInt16(param + csStart)));
222     if (IsDirectMode(VidLocal.current_mode))
223 cebix 1.1 return controlErr;
224    
225     uint32 s_pal = ReadMacInt32(param + csTable); // Source palette
226     uint8 *d_pal; // Destination palette
227 cebix 1.11 uint16 start = ReadMacInt16(param + csStart);
228 cebix 1.1 uint16 count = ReadMacInt16(param + csCount);
229 cebix 1.11 if (s_pal == 0 || count > 255)
230 cebix 1.1 return paramErr;
231    
232 cebix 1.11 if (start == 0xffff) { // Indexed
233 cebix 1.1 for (uint32 i=0; i<=count; i++) {
234 cebix 1.11 d_pal = VidLocal.palette + (ReadMacInt16(s_pal) & 0xff) * 3;
235 cebix 1.1 uint8 red = (uint16)ReadMacInt16(s_pal + 2) >> 8;
236     uint8 green = (uint16)ReadMacInt16(s_pal + 4) >> 8;
237     uint8 blue = (uint16)ReadMacInt16(s_pal + 6) >> 8;
238     if (VidLocal.luminance_mapping)
239     red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16;
240 cebix 1.11 //!! gamma correction
241 cebix 1.1 *d_pal++ = red;
242     *d_pal++ = green;
243     *d_pal++ = blue;
244     s_pal += 8;
245     }
246 cebix 1.11 } else { // Sequential
247     if (start + count > 255)
248     return paramErr;
249     d_pal = VidLocal.palette + start * 3;
250 cebix 1.1 for (uint32 i=0; i<=count; i++) {
251     uint8 red = (uint16)ReadMacInt16(s_pal + 2) >> 8;
252     uint8 green = (uint16)ReadMacInt16(s_pal + 4) >> 8;
253     uint8 blue = (uint16)ReadMacInt16(s_pal + 6) >> 8;
254     if (VidLocal.luminance_mapping)
255     red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16;
256 cebix 1.11 //!! gamma correction
257 cebix 1.1 *d_pal++ = red;
258     *d_pal++ = green;
259     *d_pal++ = blue;
260     s_pal += 8;
261     }
262     }
263     video_set_palette(VidLocal.palette);
264     return noErr;
265     }
266    
267     case cscSetGamma: // Set gamma table
268     D(bug(" SetGamma\n"));
269 cebix 1.9 //!!
270 cebix 1.11 return controlErr;
271 cebix 1.1
272     case cscGrayPage: { // Fill page with dithered gray pattern
273     D(bug(" GrayPage %d\n", ReadMacInt16(param + csPage)));
274     if (ReadMacInt16(param + csPage))
275     return paramErr;
276    
277     uint32 pattern[6] = {
278     0xaaaaaaaa, // 1 bpp
279     0xcccccccc, // 2 bpp
280     0xf0f0f0f0, // 4 bpp
281     0xff00ff00, // 8 bpp
282     0xffff0000, // 16 bpp
283     0xffffffff // 32 bpp
284     };
285     uint32 p = VidLocal.desc->mac_frame_base;
286 cebix 1.9 uint32 pat = pattern[VidLocal.desc->mode.depth];
287 cebix 1.11 bool invert = (VidLocal.desc->mode.depth == VDEPTH_32BIT);
288 cebix 1.9 for (uint32 y=0; y<VidLocal.desc->mode.y; y++) {
289     for (uint32 x=0; x<VidLocal.desc->mode.bytes_per_row; x+=4) {
290 cebix 1.8 WriteMacInt32(p + x, pat);
291 cebix 1.11 if (invert)
292 cebix 1.1 pat = ~pat;
293     }
294 cebix 1.9 p += VidLocal.desc->mode.bytes_per_row;
295 cebix 1.1 pat = ~pat;
296     }
297 cebix 1.11 //!! if direct mode, load gamma table to CLUT
298 cebix 1.1 return noErr;
299     }
300    
301     case cscSetGray: // Enable/disable luminance mapping
302     D(bug(" SetGray %02x\n", ReadMacInt8(param + csMode)));
303     VidLocal.luminance_mapping = ReadMacInt8(param + csMode);
304     return noErr;
305    
306     case cscSetInterrupt: // Enable/disable VBL
307     D(bug(" SetInterrupt %02x\n", ReadMacInt8(param + csMode)));
308     VidLocal.interrupts_enabled = (ReadMacInt8(param + csMode) == 0);
309     return noErr;
310    
311 cebix 1.9 case cscSetDefaultMode: { // Set default color depth
312     uint16 mode = ReadMacInt16(param + csMode);
313     D(bug(" SetDefaultMode %04x\n", mode));
314     VidLocal.preferred_mode = mode;
315     return noErr;
316     }
317    
318     case cscSwitchMode: { // Switch video mode (depth and resolution)
319     uint16 mode = ReadMacInt16(param + csMode);
320     uint32 id = ReadMacInt32(param + csData);
321     D(bug(" SwitchMode %04x, %08x\n", mode, id));
322 cebix 1.10
323 cebix 1.11 // Set old base address in case the switch fails
324     WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base);
325    
326     if (ReadMacInt16(param + csPage))
327     return paramErr;
328    
329 cebix 1.10 if (mode != VidLocal.current_mode || id != VidLocal.current_id) {
330     std::vector<video_mode>::const_iterator i = find_mode(mode, id);
331 cebix 1.11 if (i == VideoModes.end())
332 cebix 1.10 return paramErr;
333 cebix 1.11 set_gray_palette();
334 cebix 1.10 video_switch_to_mode(*i);
335     VidLocal.current_mode = mode;
336     VidLocal.current_id = id;
337 cebix 1.11 uint32 frame_base = VidLocal.desc->mac_frame_base;
338     WriteMacInt32(param + csBaseAddr, frame_base);
339    
340     M68kRegisters r;
341     uint32 sp = VidLocal.sp;
342     r.a[0] = sp;
343    
344     // Find functional sResource for this display
345     WriteMacInt8(sp + spSlot, ReadMacInt8(dce + dCtlSlot));
346     WriteMacInt8(sp + spID, ReadMacInt8(dce + dCtlSlotId));
347     WriteMacInt8(sp + spExtDev, 0);
348     r.d[0] = 0x0016;
349     Execute68kTrap(0xa06e, &r); // SRsrcInfo()
350     uint32 rsrc = ReadMacInt32(sp + spPointer);
351    
352     // Patch minorBase
353     WriteMacInt8(sp + spID, 0x0a); // minorBase
354     r.d[0] = 0x0006;
355     Execute68kTrap(0xa06e, &r); // SFindStruct()
356     uint32 minor_base = ReadMacInt32(sp + spPointer) - ROMBaseMac;
357     ROMBaseHost[minor_base + 0] = frame_base >> 24;
358     ROMBaseHost[minor_base + 1] = frame_base >> 16;
359     ROMBaseHost[minor_base + 2] = frame_base >> 8;
360     ROMBaseHost[minor_base + 3] = frame_base;
361    
362     // Patch video mode parameter table
363     WriteMacInt32(sp + spPointer, rsrc);
364     WriteMacInt8(sp + spID, mode);
365     r.d[0] = 0x0006;
366     Execute68kTrap(0xa06e, &r); // SFindStruct()
367     WriteMacInt8(sp + spID, 0x01);
368     r.d[0] = 0x0006;
369     Execute68kTrap(0xa06e, &r); // SFindStruct()
370     uint32 p = ReadMacInt32(sp + spPointer) - ROMBaseMac;
371     ROMBaseHost[p + 8] = i->bytes_per_row >> 8;
372     ROMBaseHost[p + 9] = i->bytes_per_row;
373     ROMBaseHost[p + 14] = i->y >> 8;
374     ROMBaseHost[p + 15] = i->y;
375     ROMBaseHost[p + 16] = i->x >> 8;
376     ROMBaseHost[p + 17] = i->x;
377    
378     // Update sResource
379     WriteMacInt8(sp + spID, ReadMacInt8(dce + dCtlSlotId));
380     r.d[0] = 0x002b;
381     Execute68kTrap(0xa06e, &r); // SUpdateSRT()
382    
383     // Update frame buffer base in DCE
384     WriteMacInt32(dce + dCtlDevBase, frame_base);
385 cebix 1.10 }
386 cebix 1.11 D(bug(" base %08x\n", VidLocal.desc->mac_frame_base));
387 cebix 1.10 return noErr;
388 cebix 1.9 }
389    
390     case cscSavePreferredConfiguration: {
391     uint16 mode = ReadMacInt16(param + csMode);
392     uint32 id = ReadMacInt32(param + csData);
393     D(bug(" SavePreferredConfiguration %04x, %08x\n", mode, id));
394     VidLocal.preferred_mode = mode;
395     VidLocal.preferred_id = id;
396     return noErr;
397     }
398    
399 cebix 1.1 default:
400 cebix 1.2 printf("WARNING: Unknown VideoDriverControl(%d)\n", code);
401 cebix 1.1 return controlErr;
402     }
403     }
404    
405    
406     /*
407     * Driver Status() routine
408     */
409    
410 cebix 1.2 int16 VideoDriverStatus(uint32 pb, uint32 dce)
411 cebix 1.1 {
412     uint16 code = ReadMacInt16(pb + csCode);
413     uint32 param = ReadMacInt32(pb + csParam);
414 cebix 1.2 D(bug("VideoDriverStatus %d\n", code));
415 cebix 1.1 switch (code) {
416    
417 cebix 1.9 case cscGetMode: // Get current color depth
418     D(bug(" GetMode -> %04x, base %08x\n", VidLocal.current_mode, VidLocal.desc->mac_frame_base));
419     WriteMacInt16(param + csMode, VidLocal.current_mode);
420     WriteMacInt16(param + csPage, 0);
421     WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base);
422     return noErr;
423    
424 cebix 1.11 case cscGetEntries: { // Read palette
425     D(bug(" GetEntries table %08x, count %d, start %d\n", ReadMacInt32(param + csTable), ReadMacInt16(param + csCount), ReadMacInt16(param + csStart)));
426 cebix 1.9
427 cebix 1.11 uint8 *s_pal; // Source palette
428     uint32 d_pal = ReadMacInt32(param + csTable); // Destination palette
429     uint16 start = ReadMacInt16(param + csStart);
430     uint16 count = ReadMacInt16(param + csCount);
431     if (d_pal == 0 || count > 255)
432     return paramErr;
433    
434     if (start == 0xffff) { // Indexed
435     for (uint32 i=0; i<=count; i++) {
436     s_pal = VidLocal.palette + (ReadMacInt16(d_pal) & 0xff) * 3;
437     uint8 red = *s_pal++;
438     uint8 green = *s_pal++;
439     uint8 blue = *s_pal++;
440     WriteMacInt16(d_pal + 2, red * 0x0101);
441     WriteMacInt16(d_pal + 4, green * 0x0101);
442     WriteMacInt16(d_pal + 6, blue * 0x0101);
443     d_pal += 8;
444     }
445     } else { // Sequential
446     if (start + count > 255)
447     return paramErr;
448     s_pal = VidLocal.palette + start * 3;
449     for (uint32 i=0; i<=count; i++) {
450     uint8 red = *s_pal++;
451     uint8 green = *s_pal++;
452     uint8 blue = *s_pal++;
453     WriteMacInt16(d_pal + 2, red * 0x0101);
454     WriteMacInt16(d_pal + 4, green * 0x0101);
455     WriteMacInt16(d_pal + 6, blue * 0x0101);
456     d_pal += 8;
457     }
458     }
459     return noErr;
460     }
461    
462     case cscGetPages: // Get number of pages
463     D(bug(" GetPages -> 1\n"));
464 cebix 1.1 WriteMacInt16(param + csPage, 1);
465     return noErr;
466    
467 cebix 1.11 case cscGetBaseAddress: // Get page base address
468     D(bug(" GetBaseAddress -> %08x\n", VidLocal.desc->mac_frame_base));
469 cebix 1.1 WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base);
470 cebix 1.11 if (ReadMacInt16(param + csPage))
471     return paramErr;
472     else
473     return noErr;
474 cebix 1.1
475     case cscGetGray: // Get luminance mapping flag
476 cebix 1.9 D(bug(" GetGray -> %d\n", VidLocal.luminance_mapping));
477 cebix 1.11 WriteMacInt16(param, VidLocal.luminance_mapping ? 0x0100 : 0);
478 cebix 1.1 return noErr;
479    
480     case cscGetInterrupt: // Get interrupt disable flag
481 cebix 1.9 D(bug(" GetInterrupt -> %d\n", VidLocal.interrupts_enabled));
482 cebix 1.11 WriteMacInt16(param, VidLocal.interrupts_enabled ? 0 : 0x0100);
483 cebix 1.1 return noErr;
484    
485 cebix 1.11 case cscGetGamma:
486     D(bug(" GetGamma -> \n"));
487     //!!
488     return statusErr;
489 cebix 1.9
490     case cscGetDefaultMode: // Get default color depth
491     D(bug(" GetDefaultMode -> %04x\n", VidLocal.preferred_mode));
492     WriteMacInt16(param + csMode, VidLocal.preferred_mode);
493 cebix 1.1 return noErr;
494    
495 cebix 1.11 case cscGetCurrentMode: // Get current video mode (depth and resolution)
496     D(bug(" GetCurMode -> %04x/%08x, base %08x\n", VidLocal.current_mode, VidLocal.current_id, VidLocal.desc->mac_frame_base));
497 cebix 1.9 WriteMacInt16(param + csMode, VidLocal.current_mode);
498     WriteMacInt32(param + csData, VidLocal.current_id);
499 cebix 1.1 WriteMacInt16(param + csPage, 0);
500     WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base);
501     return noErr;
502    
503     case cscGetConnection: // Get monitor information
504     D(bug(" GetConnection\n"));
505 cebix 1.11 WriteMacInt16(param + csDisplayType, 8); // Modeless connection
506     WriteMacInt8(param + csConnectTaggedType, 0);
507     WriteMacInt8(param + csConnectTaggedData, 0);
508     WriteMacInt32(param + csConnectFlags, 0x43); // All modes valid and safe, non-standard tagging
509 cebix 1.1 WriteMacInt32(param + csDisplayComponent, 0);
510     return noErr;
511    
512 cebix 1.11 case cscGetModeTiming: { // Get video timing for specified resolution
513     uint32 id = ReadMacInt32(param + csTimingMode);
514     D(bug(" GetModeTiming %08x\n", id));
515     if (!has_resolution(id))
516     return paramErr;
517    
518     WriteMacInt32(param + csTimingFormat, FOURCC('d', 'e', 'c', 'l'));
519     WriteMacInt32(param + csTimingData, 0); // unknown
520     uint32 flags = 0xb; // mode valid, safe and shown in Monitors panel
521     if (id == VidLocal.preferred_id)
522     flags |= 4; // default mode
523     WriteMacInt32(param + csTimingFlags, flags);
524     return noErr;
525     }
526    
527 cebix 1.9 case cscGetModeBaseAddress: // Get frame buffer base address
528 cebix 1.11 D(bug(" GetModeBaseAddress -> base %08x\n", VidLocal.desc->mac_frame_base));
529     WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base);
530 cebix 1.1 return noErr;
531    
532 cebix 1.9 case cscGetPreferredConfiguration: // Get default video mode (depth and resolution)
533     D(bug(" GetPreferredConfiguration -> %04x/%08x\n", VidLocal.preferred_mode, VidLocal.preferred_id));
534     WriteMacInt16(param + csMode, VidLocal.preferred_mode);
535     WriteMacInt32(param + csData, VidLocal.preferred_id);
536     return noErr;
537    
538     case cscGetNextResolution: { // Called iteratively to obtain a list of all supported resolutions
539     uint32 id = ReadMacInt32(param + csPreviousDisplayModeID);
540     D(bug(" GetNextResolution %08x\n", id));
541    
542     switch (id) {
543     case 0:
544     // Return current resolution
545     id = VidLocal.current_id;
546     break;
547    
548     case 0xfffffffe:
549     // Return first supported resolution
550     id = 0x80;
551     while (!has_resolution(id))
552     id++;
553     break;
554    
555     default:
556     // Get next resolution
557     if (!has_resolution(id))
558     return paramErr;
559     id++;
560     while (!has_resolution(id) && id < 0x100)
561     id++;
562     if (id == 0x100) { // No more resolutions
563     WriteMacInt32(param + csRIDisplayModeID, 0xfffffffd);
564     return noErr;
565     }
566     break;
567     }
568    
569     WriteMacInt32(param + csRIDisplayModeID, id);
570     uint32 x, y;
571     get_size_of_resolution(id, x, y);
572     WriteMacInt32(param + csHorizontalPixels, x);
573     WriteMacInt32(param + csVerticalLines, y);
574     WriteMacInt32(param + csRefreshRate, 75 << 16);
575     WriteMacInt16(param + csMaxDepthMode, DepthToAppleMode(max_depth_of_resolution(id)));
576 jlachmann 1.5 return noErr;
577 cebix 1.9 }
578 jlachmann 1.5
579 cebix 1.9 case cscGetVideoParameters: { // Get information about specified resolution/depth
580     uint32 id = ReadMacInt32(param + csDisplayModeID);
581     uint16 mode = ReadMacInt16(param + csDepthMode);
582     D(bug(" GetVideoParameters %04x/%08x\n", mode, id));
583    
584     vector<video_mode>::const_iterator i = VideoModes.begin(), end = VideoModes.end();
585     while (i != end) {
586     if (DepthToAppleMode(i->depth) == mode && i->resolution_id == id) {
587     uint32 vp = ReadMacInt32(param + csVPBlockPtr);
588     WriteMacInt32(vp + vpBaseOffset, 0);
589     WriteMacInt16(vp + vpRowBytes, i->bytes_per_row);
590     WriteMacInt16(vp + vpBounds, 0);
591     WriteMacInt16(vp + vpBounds + 2, 0);
592     WriteMacInt16(vp + vpBounds + 4, i->y);
593     WriteMacInt16(vp + vpBounds + 6, i->x);
594     WriteMacInt16(vp + vpVersion, 0);
595     WriteMacInt16(vp + vpPackType, 0);
596     WriteMacInt32(vp + vpPackSize, 0);
597 cebix 1.11 WriteMacInt32(vp + vpHRes, 0x00480000); // 72 dpi
598 cebix 1.9 WriteMacInt32(vp + vpVRes, 0x00480000);
599     uint32 pix_type, pix_size, cmp_count, cmp_size, dev_type;
600     switch (i->depth) {
601     case VDEPTH_1BIT:
602     pix_type = 0; pix_size = 1;
603     cmp_count = 1; cmp_size = 1;
604     dev_type = 0; // CLUT
605     break;
606     case VDEPTH_2BIT:
607     pix_type = 0; pix_size = 2;
608     cmp_count = 1; cmp_size = 2;
609     dev_type = 0; // CLUT
610     break;
611     case VDEPTH_4BIT:
612     pix_type = 0; pix_size = 4;
613     cmp_count = 1; cmp_size = 4;
614     dev_type = 0; // CLUT
615     break;
616     case VDEPTH_8BIT:
617     pix_type = 0; pix_size = 8;
618     cmp_count = 1; cmp_size = 8;
619     dev_type = 0; // CLUT
620     break;
621     case VDEPTH_16BIT:
622     pix_type = 0x10; pix_size = 16;
623     cmp_count = 3; cmp_size = 5;
624     dev_type = 2; // direct
625     break;
626     case VDEPTH_32BIT:
627     pix_type = 0x10; pix_size = 32;
628     cmp_count = 3; cmp_size = 8;
629     dev_type = 2; // direct
630     break;
631     }
632     WriteMacInt16(vp + vpPixelType, pix_type);
633     WriteMacInt16(vp + vpPixelSize, pix_size);
634     WriteMacInt16(vp + vpCmpCount, cmp_count);
635     WriteMacInt16(vp + vpCmpSize, cmp_size);
636     WriteMacInt32(param + csPageCount, 1);
637     WriteMacInt32(param + csDeviceType, dev_type);
638     return noErr;
639     }
640     ++i;
641     }
642     return paramErr; // specified resolution/depth not supported
643     }
644 cebix 1.1
645     default:
646 cebix 1.2 printf("WARNING: Unknown VideoDriverStatus(%d)\n", code);
647 cebix 1.1 return statusErr;
648     }
649     }