ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/video.cpp
Revision: 1.18
Committed: 2001-07-01T14:38:02Z (22 years, 10 months ago) by cebix
Branch: MAIN
Changes since 1.17: +80 -75 lines
Log Message:
- sony.cpp/disk.cpp/cdrom.cpp use vector<> of drive_info objects instead of
  linked list
- color depth switching updates slot ROM
- video_x.cpp always supports 1-bit window modes
- timer_create()/clock_gettime() are pulled from librt if present

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 cebix 1.13 #include "slot_rom.h"
35 cebix 1.1 #include "video.h"
36     #include "video_defs.h"
37    
38 cebix 1.11 #define DEBUG 0
39 cebix 1.1 #include "debug.h"
40    
41    
42 cebix 1.9 // List of supported video modes
43 cebix 1.17 vector<video_mode> VideoModes;
44 cebix 1.9
45 cebix 1.1 // Description of the main monitor
46 cebix 1.9 monitor_desc VideoMonitor;
47 cebix 1.1
48     // Local variables (per monitor)
49     struct {
50 cebix 1.9 monitor_desc *desc; // Pointer to description of monitor handled by this instance of the driver
51 cebix 1.1 uint8 palette[256 * 3]; // Color palette, 256 entries, RGB
52     bool luminance_mapping; // Luminance mapping on/off
53     bool interrupts_enabled; // VBL interrupts on/off
54 cebix 1.11 uint32 gamma_table; // Mac address of gamma table
55 cebix 1.14 int alloc_gamma_table_size; // Allocated size of gamma table
56 cebix 1.9 uint16 current_mode; // Currently selected depth/resolution
57     uint32 current_id;
58     uint16 preferred_mode; // Preferred depth/resolution
59     uint32 preferred_id;
60 cebix 1.16 uint32 slot_param; // Mac address of Slot Manager parameter block
61 cebix 1.1 } VidLocal;
62    
63    
64     /*
65 cebix 1.9 * Check whether specified resolution ID is one of the supported resolutions
66     */
67    
68     static bool has_resolution(uint32 id)
69     {
70 cebix 1.18 vector<video_mode>::const_iterator i, end = VideoModes.end();
71     for (i = VideoModes.begin(); i != end; ++i) {
72 cebix 1.9 if (i->resolution_id == id)
73     return true;
74     }
75     return false;
76     }
77    
78    
79     /*
80 cebix 1.10 * Find specified mode (depth/resolution) (or VideoModes.end() if not found)
81     */
82    
83 cebix 1.17 static vector<video_mode>::const_iterator find_mode(uint16 mode, uint32 id)
84 cebix 1.10 {
85 cebix 1.18 vector<video_mode>::const_iterator i, end = VideoModes.end();
86     for (i = VideoModes.begin(); i != end; ++i) {
87 cebix 1.10 if (i->resolution_id == id && DepthToAppleMode(i->depth) == mode)
88     return 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 cebix 1.18 vector<video_mode>::const_iterator i, end = VideoModes.end();
102     for (i = VideoModes.begin(); i != end; ++i) {
103 cebix 1.9 if (i->depth > m)
104     m = i->depth;
105     }
106     return m;
107     }
108    
109    
110     /*
111     * Get X/Y size of specified resolution
112     */
113    
114     static void get_size_of_resolution(uint32 id, uint32 &x, uint32 &y)
115     {
116 cebix 1.18 vector<video_mode>::const_iterator i, end = VideoModes.end();
117     for (i = VideoModes.begin(); i != end; ++i) {
118 cebix 1.9 if (i->resolution_id == id) {
119     x = i->x;
120     y = i->y;
121     return;
122     }
123     }
124     }
125    
126    
127     /*
128 cebix 1.11 * Set palette to 50% gray
129     */
130    
131     static void set_gray_palette(void)
132     {
133 cebix 1.14 for (int i=0; i<256; i++) {
134     VidLocal.palette[i * 3 + 0] = 127;
135     VidLocal.palette[i * 3 + 1] = 127;
136     VidLocal.palette[i * 3 + 2] = 127;
137     }
138     video_set_palette(VidLocal.palette);
139     }
140    
141    
142     /*
143     * Load gamma-corrected black-to-white ramp to palette for direct-color mode
144     */
145    
146     static void load_ramp_palette(void)
147     {
148     // Find tables for gamma correction
149     uint8 *red_gamma, *green_gamma, *blue_gamma;
150     bool have_gamma = false;
151     int data_width = 0;
152     if (VidLocal.gamma_table) {
153     uint32 table = VidLocal.gamma_table;
154     red_gamma = Mac2HostAddr(table + gFormulaData + ReadMacInt16(table + gFormulaSize));
155     int chan_cnt = ReadMacInt16(table + gChanCnt);
156     if (chan_cnt == 1)
157     green_gamma = blue_gamma = red_gamma;
158     else {
159     int ofs = ReadMacInt16(table + gDataCnt);
160     green_gamma = red_gamma + ofs;
161     blue_gamma = green_gamma + ofs;
162     }
163     data_width = ReadMacInt16(table + gDataWidth);
164     have_gamma = true;
165     }
166    
167     int num = (VidLocal.desc->mode.depth == VDEPTH_16BIT ? 32 : 256);
168     uint8 *p = VidLocal.palette;
169     for (int i=0; i<num; i++) {
170 cebix 1.15 uint8 red = (i * 256 / num), green = red, blue = red;
171 cebix 1.14 if (have_gamma) {
172     red = red_gamma[red >> (8 - data_width)];
173     green = green_gamma[green >> (8 - data_width)];
174     blue = blue_gamma[blue >> (8 - data_width)];
175     }
176     *p++ = red;
177     *p++ = green;
178     *p++ = blue;
179     }
180    
181     video_set_palette(VidLocal.palette);
182     }
183    
184    
185     /*
186     * Allocate gamma table of specified size
187     */
188    
189     static bool allocate_gamma_table(int size)
190     {
191     M68kRegisters r;
192    
193     if (size > VidLocal.alloc_gamma_table_size) {
194     if (VidLocal.gamma_table) {
195     r.a[0] = VidLocal.gamma_table;
196     Execute68kTrap(0xa01f, &r); // DisposePtr()
197     VidLocal.gamma_table = 0;
198     VidLocal.alloc_gamma_table_size = 0;
199 cebix 1.11 }
200 cebix 1.14 r.d[0] = size;
201     Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
202     if (r.a[0] == 0)
203     return false;
204     VidLocal.gamma_table = r.a[0];
205     VidLocal.alloc_gamma_table_size = size;
206 cebix 1.11 }
207 cebix 1.14 return true;
208     }
209    
210    
211     /*
212     * Set gamma table (0 = build linear ramp)
213     */
214    
215     static bool set_gamma_table(uint32 user_table)
216     {
217     if (user_table == 0) { // Build linear ramp, 256 entries
218    
219     // Allocate new table, if necessary
220     if (!allocate_gamma_table(SIZEOF_GammaTbl + 256))
221     return memFullErr;
222     uint32 table = VidLocal.gamma_table;
223    
224     // Initialize header
225     WriteMacInt16(table + gVersion, 0);
226     WriteMacInt16(table + gType, 0);
227     WriteMacInt16(table + gFormulaSize, 0);
228     WriteMacInt16(table + gChanCnt, 1);
229     WriteMacInt16(table + gDataCnt, 256);
230     WriteMacInt16(table + gDataWidth, 8);
231    
232     // Build ramp
233     uint32 p = table + gFormulaData;
234     for (int i=0; i<256; i++)
235     WriteMacInt8(p + i, i);
236    
237     } else { // User-supplied gamma table
238    
239     // Validate header
240     if (ReadMacInt16(user_table + gVersion))
241     return paramErr;
242     if (ReadMacInt16(user_table + gType))
243     return paramErr;
244     int chan_cnt = ReadMacInt16(user_table + gChanCnt);
245     if (chan_cnt != 1 && chan_cnt != 3)
246     return paramErr;
247     int data_width = ReadMacInt16(user_table + gDataWidth);
248     if (data_width > 8)
249     return paramErr;
250     int data_cnt = ReadMacInt16(user_table + gDataCnt);
251     if (data_cnt != (1 << data_width))
252     return paramErr;
253    
254     // Allocate new table, if necessary
255     int size = SIZEOF_GammaTbl + ReadMacInt16(user_table + gFormulaSize) + chan_cnt * data_cnt;
256     if (!allocate_gamma_table(size))
257     return memFullErr;
258     uint32 table = VidLocal.gamma_table;
259    
260     // Copy table
261     Mac2Mac_memcpy(table, user_table, size);
262     }
263    
264     if (IsDirectMode(VidLocal.current_mode))
265     load_ramp_palette();
266    
267     return true;
268 cebix 1.11 }
269    
270    
271     /*
272 cebix 1.18 * Switch video mode
273     */
274    
275     static void switch_mode(const video_mode &mode, uint32 param, uint32 dce)
276     {
277     // Switch mode
278     set_gray_palette();
279     video_switch_to_mode(mode);
280    
281     // Update VidLocal
282     VidLocal.current_mode = DepthToAppleMode(mode.depth);
283     VidLocal.current_id = mode.resolution_id;
284    
285     uint32 frame_base = VidLocal.desc->mac_frame_base;
286    
287     M68kRegisters r;
288     uint32 sp = VidLocal.slot_param;
289     r.a[0] = sp;
290    
291     // Find functional sResource for this display
292     WriteMacInt8(sp + spSlot, ReadMacInt8(dce + dCtlSlot));
293     WriteMacInt8(sp + spID, ReadMacInt8(dce + dCtlSlotId));
294     WriteMacInt8(sp + spExtDev, 0);
295     r.d[0] = 0x0016;
296     Execute68kTrap(0xa06e, &r); // SRsrcInfo()
297     uint32 rsrc = ReadMacInt32(sp + spPointer);
298    
299     // Patch minorBase (otherwise rebooting won't work)
300     WriteMacInt8(sp + spID, 0x0a); // minorBase
301     r.d[0] = 0x0006;
302     Execute68kTrap(0xa06e, &r); // SFindStruct()
303     uint32 minor_base = ReadMacInt32(sp + spPointer) - ROMBaseMac;
304     ROMBaseHost[minor_base + 0] = frame_base >> 24;
305     ROMBaseHost[minor_base + 1] = frame_base >> 16;
306     ROMBaseHost[minor_base + 2] = frame_base >> 8;
307     ROMBaseHost[minor_base + 3] = frame_base;
308    
309     // Patch video mode parameter table
310     WriteMacInt32(sp + spPointer, rsrc);
311     WriteMacInt8(sp + spID, DepthToAppleMode(mode.depth));
312     r.d[0] = 0x0006;
313     Execute68kTrap(0xa06e, &r); // SFindStruct()
314     WriteMacInt8(sp + spID, 0x01);
315     r.d[0] = 0x0006;
316     Execute68kTrap(0xa06e, &r); // SFindStruct()
317     uint32 p = ReadMacInt32(sp + spPointer) - ROMBaseMac;
318     ROMBaseHost[p + 8] = mode.bytes_per_row >> 8;
319     ROMBaseHost[p + 9] = mode.bytes_per_row;
320     ROMBaseHost[p + 14] = mode.y >> 8;
321     ROMBaseHost[p + 15] = mode.y;
322     ROMBaseHost[p + 16] = mode.x >> 8;
323     ROMBaseHost[p + 17] = mode.x;
324    
325     // Recalculate slot ROM checksum
326     ChecksumSlotROM();
327    
328     // Update sResource
329     WriteMacInt8(sp + spID, ReadMacInt8(dce + dCtlSlotId));
330     r.d[0] = 0x002b;
331     Execute68kTrap(0xa06e, &r); // SUpdateSRT()
332    
333     // Update frame buffer base in DCE and param block
334     WriteMacInt32(dce + dCtlDevBase, frame_base);
335     WriteMacInt32(param + csBaseAddr, frame_base);
336     }
337    
338    
339     /*
340 cebix 1.1 * Driver Open() routine
341     */
342    
343 cebix 1.2 int16 VideoDriverOpen(uint32 pb, uint32 dce)
344 cebix 1.1 {
345 cebix 1.2 D(bug("VideoDriverOpen\n"));
346 cebix 1.1
347 cebix 1.9 // This shouldn't happen unless the platform-specific video code is broken
348     if (VideoModes.empty())
349     fprintf(stderr, "No valid video modes found (broken video driver?)\n");
350    
351 cebix 1.1 // Init local variables
352     VidLocal.desc = &VideoMonitor;
353     VidLocal.luminance_mapping = false;
354     VidLocal.interrupts_enabled = false;
355 cebix 1.9 VidLocal.current_mode = DepthToAppleMode(VidLocal.desc->mode.depth);
356     VidLocal.current_id = VidLocal.desc->mode.resolution_id;
357     VidLocal.preferred_mode = VidLocal.current_mode;
358     VidLocal.preferred_id = VidLocal.current_id;
359 cebix 1.1
360 cebix 1.11 // Allocate Slot Manager parameter block in Mac RAM
361     M68kRegisters r;
362     r.d[0] = SIZEOF_SPBlock;
363     Execute68kTrap(0xa71e, &r); // NewPtrSysClear()
364     if (r.a[0] == 0)
365     return memFullErr;
366 cebix 1.16 VidLocal.slot_param = r.a[0];
367     D(bug("SPBlock at %08x\n", VidLocal.slot_param));
368 cebix 1.11
369     // Find and set default gamma table
370 cebix 1.14 VidLocal.gamma_table = 0;
371     VidLocal.alloc_gamma_table_size = 0;
372     set_gamma_table(0);
373 cebix 1.11
374 cebix 1.1 // Init color palette (solid gray)
375 cebix 1.11 set_gray_palette();
376 cebix 1.1 return noErr;
377     }
378    
379    
380     /*
381     * Driver Control() routine
382     */
383    
384 cebix 1.2 int16 VideoDriverControl(uint32 pb, uint32 dce)
385 cebix 1.1 {
386     uint16 code = ReadMacInt16(pb + csCode);
387     uint32 param = ReadMacInt32(pb + csParam);
388 cebix 1.2 D(bug("VideoDriverControl %d\n", code));
389 cebix 1.1 switch (code) {
390    
391 cebix 1.9 case cscSetMode: { // Set color depth
392     uint16 mode = ReadMacInt16(param + csMode);
393     D(bug(" SetMode %04x\n", mode));
394 cebix 1.10
395 cebix 1.11 // Set old base address in case the switch fails
396     WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base);
397    
398     if (ReadMacInt16(param + csPage))
399     return paramErr;
400    
401 cebix 1.10 if (mode != VidLocal.current_mode) {
402 cebix 1.17 vector<video_mode>::const_iterator i = find_mode(mode, VidLocal.current_id);
403 cebix 1.11 if (i == VideoModes.end())
404 cebix 1.10 return paramErr;
405 cebix 1.18 switch_mode(*i, param, dce);
406 cebix 1.10 }
407 cebix 1.11 D(bug(" base %08x\n", VidLocal.desc->mac_frame_base));
408 cebix 1.10 return noErr;
409 cebix 1.9 }
410 cebix 1.1
411 cebix 1.14 case cscSetEntries: // Set palette
412     case cscDirectSetEntries: {
413     D(bug(" (Direct)SetEntries table %08x, count %d, start %d\n", ReadMacInt32(param + csTable), ReadMacInt16(param + csCount), ReadMacInt16(param + csStart)));
414     bool is_direct = IsDirectMode(VidLocal.current_mode);
415     if (code == cscSetEntries && is_direct)
416     return controlErr;
417     if (code == cscDirectSetEntries && !is_direct)
418 cebix 1.1 return controlErr;
419    
420     uint32 s_pal = ReadMacInt32(param + csTable); // Source palette
421     uint8 *d_pal; // Destination palette
422 cebix 1.11 uint16 start = ReadMacInt16(param + csStart);
423 cebix 1.1 uint16 count = ReadMacInt16(param + csCount);
424 cebix 1.11 if (s_pal == 0 || count > 255)
425 cebix 1.1 return paramErr;
426    
427 cebix 1.14 // Find tables for gamma correction
428     uint8 *red_gamma, *green_gamma, *blue_gamma;
429     bool have_gamma = false;
430     int data_width = 0;
431     if (VidLocal.gamma_table) {
432     uint32 table = VidLocal.gamma_table;
433     red_gamma = Mac2HostAddr(table + gFormulaData + ReadMacInt16(table + gFormulaSize));
434     int chan_cnt = ReadMacInt16(table + gChanCnt);
435     if (chan_cnt == 1)
436     green_gamma = blue_gamma = red_gamma;
437     else {
438     int ofs = ReadMacInt16(table + gDataCnt);
439     green_gamma = red_gamma + ofs;
440     blue_gamma = green_gamma + ofs;
441     }
442     data_width = ReadMacInt16(table + gDataWidth);
443     have_gamma = true;
444     }
445    
446     // Convert palette
447 cebix 1.11 if (start == 0xffff) { // Indexed
448 cebix 1.1 for (uint32 i=0; i<=count; i++) {
449 cebix 1.11 d_pal = VidLocal.palette + (ReadMacInt16(s_pal) & 0xff) * 3;
450 cebix 1.1 uint8 red = (uint16)ReadMacInt16(s_pal + 2) >> 8;
451     uint8 green = (uint16)ReadMacInt16(s_pal + 4) >> 8;
452     uint8 blue = (uint16)ReadMacInt16(s_pal + 6) >> 8;
453 cebix 1.14 if (VidLocal.luminance_mapping && !is_direct)
454 cebix 1.1 red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16;
455 cebix 1.14 if (have_gamma) {
456     red = red_gamma[red >> (8 - data_width)];
457     green = green_gamma[green >> (8 - data_width)];
458     blue = blue_gamma[blue >> (8 - data_width)];
459     }
460 cebix 1.1 *d_pal++ = red;
461     *d_pal++ = green;
462     *d_pal++ = blue;
463     s_pal += 8;
464     }
465 cebix 1.11 } else { // Sequential
466     if (start + count > 255)
467     return paramErr;
468     d_pal = VidLocal.palette + start * 3;
469 cebix 1.1 for (uint32 i=0; i<=count; i++) {
470     uint8 red = (uint16)ReadMacInt16(s_pal + 2) >> 8;
471     uint8 green = (uint16)ReadMacInt16(s_pal + 4) >> 8;
472     uint8 blue = (uint16)ReadMacInt16(s_pal + 6) >> 8;
473 cebix 1.14 if (VidLocal.luminance_mapping && !is_direct)
474 cebix 1.1 red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16;
475 cebix 1.14 if (have_gamma) {
476     red = red_gamma[red >> (8 - data_width)];
477     green = green_gamma[green >> (8 - data_width)];
478     blue = blue_gamma[blue >> (8 - data_width)];
479     }
480 cebix 1.1 *d_pal++ = red;
481     *d_pal++ = green;
482     *d_pal++ = blue;
483     s_pal += 8;
484     }
485     }
486     video_set_palette(VidLocal.palette);
487     return noErr;
488     }
489    
490 cebix 1.14 case cscSetGamma: { // Set gamma table
491     uint32 user_table = ReadMacInt32(param + csGTable);
492     D(bug(" SetGamma %08x\n", user_table));
493     return set_gamma_table(user_table) ? noErr : memFullErr;
494     }
495 cebix 1.1
496     case cscGrayPage: { // Fill page with dithered gray pattern
497     D(bug(" GrayPage %d\n", ReadMacInt16(param + csPage)));
498     if (ReadMacInt16(param + csPage))
499     return paramErr;
500    
501     uint32 pattern[6] = {
502     0xaaaaaaaa, // 1 bpp
503     0xcccccccc, // 2 bpp
504     0xf0f0f0f0, // 4 bpp
505     0xff00ff00, // 8 bpp
506     0xffff0000, // 16 bpp
507     0xffffffff // 32 bpp
508     };
509     uint32 p = VidLocal.desc->mac_frame_base;
510 cebix 1.9 uint32 pat = pattern[VidLocal.desc->mode.depth];
511 cebix 1.11 bool invert = (VidLocal.desc->mode.depth == VDEPTH_32BIT);
512 cebix 1.9 for (uint32 y=0; y<VidLocal.desc->mode.y; y++) {
513     for (uint32 x=0; x<VidLocal.desc->mode.bytes_per_row; x+=4) {
514 cebix 1.8 WriteMacInt32(p + x, pat);
515 cebix 1.11 if (invert)
516 cebix 1.1 pat = ~pat;
517     }
518 cebix 1.9 p += VidLocal.desc->mode.bytes_per_row;
519 cebix 1.1 pat = ~pat;
520     }
521 cebix 1.14
522     if (IsDirectMode(VidLocal.current_mode))
523     load_ramp_palette();
524    
525 cebix 1.1 return noErr;
526     }
527    
528     case cscSetGray: // Enable/disable luminance mapping
529     D(bug(" SetGray %02x\n", ReadMacInt8(param + csMode)));
530     VidLocal.luminance_mapping = ReadMacInt8(param + csMode);
531     return noErr;
532    
533     case cscSetInterrupt: // Enable/disable VBL
534     D(bug(" SetInterrupt %02x\n", ReadMacInt8(param + csMode)));
535     VidLocal.interrupts_enabled = (ReadMacInt8(param + csMode) == 0);
536     return noErr;
537    
538 cebix 1.9 case cscSetDefaultMode: { // Set default color depth
539     uint16 mode = ReadMacInt16(param + csMode);
540     D(bug(" SetDefaultMode %04x\n", mode));
541     VidLocal.preferred_mode = mode;
542     return noErr;
543     }
544    
545     case cscSwitchMode: { // Switch video mode (depth and resolution)
546     uint16 mode = ReadMacInt16(param + csMode);
547     uint32 id = ReadMacInt32(param + csData);
548     D(bug(" SwitchMode %04x, %08x\n", mode, id));
549 cebix 1.10
550 cebix 1.11 // Set old base address in case the switch fails
551     WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base);
552    
553     if (ReadMacInt16(param + csPage))
554     return paramErr;
555    
556 cebix 1.10 if (mode != VidLocal.current_mode || id != VidLocal.current_id) {
557 cebix 1.17 vector<video_mode>::const_iterator i = find_mode(mode, id);
558 cebix 1.11 if (i == VideoModes.end())
559 cebix 1.10 return paramErr;
560 cebix 1.18 switch_mode(*i, param, dce);
561 cebix 1.10 }
562 cebix 1.11 D(bug(" base %08x\n", VidLocal.desc->mac_frame_base));
563 cebix 1.10 return noErr;
564 cebix 1.9 }
565    
566     case cscSavePreferredConfiguration: {
567     uint16 mode = ReadMacInt16(param + csMode);
568     uint32 id = ReadMacInt32(param + csData);
569     D(bug(" SavePreferredConfiguration %04x, %08x\n", mode, id));
570     VidLocal.preferred_mode = mode;
571     VidLocal.preferred_id = id;
572     return noErr;
573     }
574    
575 cebix 1.1 default:
576 cebix 1.2 printf("WARNING: Unknown VideoDriverControl(%d)\n", code);
577 cebix 1.1 return controlErr;
578     }
579     }
580    
581    
582     /*
583     * Driver Status() routine
584     */
585    
586 cebix 1.2 int16 VideoDriverStatus(uint32 pb, uint32 dce)
587 cebix 1.1 {
588     uint16 code = ReadMacInt16(pb + csCode);
589     uint32 param = ReadMacInt32(pb + csParam);
590 cebix 1.2 D(bug("VideoDriverStatus %d\n", code));
591 cebix 1.1 switch (code) {
592    
593 cebix 1.9 case cscGetMode: // Get current color depth
594     D(bug(" GetMode -> %04x, base %08x\n", VidLocal.current_mode, VidLocal.desc->mac_frame_base));
595     WriteMacInt16(param + csMode, VidLocal.current_mode);
596     WriteMacInt16(param + csPage, 0);
597     WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base);
598     return noErr;
599    
600 cebix 1.11 case cscGetEntries: { // Read palette
601     D(bug(" GetEntries table %08x, count %d, start %d\n", ReadMacInt32(param + csTable), ReadMacInt16(param + csCount), ReadMacInt16(param + csStart)));
602 cebix 1.9
603 cebix 1.11 uint8 *s_pal; // Source palette
604     uint32 d_pal = ReadMacInt32(param + csTable); // Destination palette
605     uint16 start = ReadMacInt16(param + csStart);
606     uint16 count = ReadMacInt16(param + csCount);
607     if (d_pal == 0 || count > 255)
608     return paramErr;
609    
610     if (start == 0xffff) { // Indexed
611     for (uint32 i=0; i<=count; i++) {
612     s_pal = VidLocal.palette + (ReadMacInt16(d_pal) & 0xff) * 3;
613     uint8 red = *s_pal++;
614     uint8 green = *s_pal++;
615     uint8 blue = *s_pal++;
616     WriteMacInt16(d_pal + 2, red * 0x0101);
617     WriteMacInt16(d_pal + 4, green * 0x0101);
618     WriteMacInt16(d_pal + 6, blue * 0x0101);
619     d_pal += 8;
620     }
621     } else { // Sequential
622     if (start + count > 255)
623     return paramErr;
624     s_pal = VidLocal.palette + start * 3;
625     for (uint32 i=0; i<=count; i++) {
626     uint8 red = *s_pal++;
627     uint8 green = *s_pal++;
628     uint8 blue = *s_pal++;
629     WriteMacInt16(d_pal + 2, red * 0x0101);
630     WriteMacInt16(d_pal + 4, green * 0x0101);
631     WriteMacInt16(d_pal + 6, blue * 0x0101);
632     d_pal += 8;
633     }
634     }
635     return noErr;
636     }
637    
638     case cscGetPages: // Get number of pages
639     D(bug(" GetPages -> 1\n"));
640 cebix 1.1 WriteMacInt16(param + csPage, 1);
641     return noErr;
642    
643 cebix 1.11 case cscGetBaseAddress: // Get page base address
644     D(bug(" GetBaseAddress -> %08x\n", VidLocal.desc->mac_frame_base));
645 cebix 1.1 WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base);
646 cebix 1.11 if (ReadMacInt16(param + csPage))
647     return paramErr;
648     else
649     return noErr;
650 cebix 1.1
651     case cscGetGray: // Get luminance mapping flag
652 cebix 1.9 D(bug(" GetGray -> %d\n", VidLocal.luminance_mapping));
653 cebix 1.11 WriteMacInt16(param, VidLocal.luminance_mapping ? 0x0100 : 0);
654 cebix 1.1 return noErr;
655    
656     case cscGetInterrupt: // Get interrupt disable flag
657 cebix 1.9 D(bug(" GetInterrupt -> %d\n", VidLocal.interrupts_enabled));
658 cebix 1.11 WriteMacInt16(param, VidLocal.interrupts_enabled ? 0 : 0x0100);
659 cebix 1.1 return noErr;
660    
661 cebix 1.11 case cscGetGamma:
662 cebix 1.14 D(bug(" GetGamma -> %08x\n", VidLocal.gamma_table));
663     WriteMacInt32(param + csGTable, VidLocal.gamma_table);
664     return noErr;
665 cebix 1.9
666     case cscGetDefaultMode: // Get default color depth
667     D(bug(" GetDefaultMode -> %04x\n", VidLocal.preferred_mode));
668     WriteMacInt16(param + csMode, VidLocal.preferred_mode);
669 cebix 1.1 return noErr;
670    
671 cebix 1.11 case cscGetCurrentMode: // Get current video mode (depth and resolution)
672     D(bug(" GetCurMode -> %04x/%08x, base %08x\n", VidLocal.current_mode, VidLocal.current_id, VidLocal.desc->mac_frame_base));
673 cebix 1.9 WriteMacInt16(param + csMode, VidLocal.current_mode);
674     WriteMacInt32(param + csData, VidLocal.current_id);
675 cebix 1.1 WriteMacInt16(param + csPage, 0);
676     WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base);
677     return noErr;
678    
679     case cscGetConnection: // Get monitor information
680     D(bug(" GetConnection\n"));
681 cebix 1.11 WriteMacInt16(param + csDisplayType, 8); // Modeless connection
682     WriteMacInt8(param + csConnectTaggedType, 0);
683     WriteMacInt8(param + csConnectTaggedData, 0);
684     WriteMacInt32(param + csConnectFlags, 0x43); // All modes valid and safe, non-standard tagging
685 cebix 1.1 WriteMacInt32(param + csDisplayComponent, 0);
686     return noErr;
687    
688 cebix 1.11 case cscGetModeTiming: { // Get video timing for specified resolution
689     uint32 id = ReadMacInt32(param + csTimingMode);
690     D(bug(" GetModeTiming %08x\n", id));
691     if (!has_resolution(id))
692     return paramErr;
693    
694     WriteMacInt32(param + csTimingFormat, FOURCC('d', 'e', 'c', 'l'));
695     WriteMacInt32(param + csTimingData, 0); // unknown
696     uint32 flags = 0xb; // mode valid, safe and shown in Monitors panel
697     if (id == VidLocal.preferred_id)
698     flags |= 4; // default mode
699     WriteMacInt32(param + csTimingFlags, flags);
700     return noErr;
701     }
702    
703 cebix 1.9 case cscGetModeBaseAddress: // Get frame buffer base address
704 cebix 1.11 D(bug(" GetModeBaseAddress -> base %08x\n", VidLocal.desc->mac_frame_base));
705     WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base);
706 cebix 1.1 return noErr;
707    
708 cebix 1.9 case cscGetPreferredConfiguration: // Get default video mode (depth and resolution)
709     D(bug(" GetPreferredConfiguration -> %04x/%08x\n", VidLocal.preferred_mode, VidLocal.preferred_id));
710     WriteMacInt16(param + csMode, VidLocal.preferred_mode);
711     WriteMacInt32(param + csData, VidLocal.preferred_id);
712     return noErr;
713    
714     case cscGetNextResolution: { // Called iteratively to obtain a list of all supported resolutions
715     uint32 id = ReadMacInt32(param + csPreviousDisplayModeID);
716     D(bug(" GetNextResolution %08x\n", id));
717    
718     switch (id) {
719     case 0:
720     // Return current resolution
721     id = VidLocal.current_id;
722     break;
723    
724     case 0xfffffffe:
725     // Return first supported resolution
726     id = 0x80;
727     while (!has_resolution(id))
728     id++;
729     break;
730    
731     default:
732     // Get next resolution
733     if (!has_resolution(id))
734     return paramErr;
735     id++;
736     while (!has_resolution(id) && id < 0x100)
737     id++;
738     if (id == 0x100) { // No more resolutions
739     WriteMacInt32(param + csRIDisplayModeID, 0xfffffffd);
740     return noErr;
741     }
742     break;
743     }
744    
745     WriteMacInt32(param + csRIDisplayModeID, id);
746     uint32 x, y;
747     get_size_of_resolution(id, x, y);
748     WriteMacInt32(param + csHorizontalPixels, x);
749     WriteMacInt32(param + csVerticalLines, y);
750     WriteMacInt32(param + csRefreshRate, 75 << 16);
751     WriteMacInt16(param + csMaxDepthMode, DepthToAppleMode(max_depth_of_resolution(id)));
752 jlachmann 1.5 return noErr;
753 cebix 1.9 }
754 jlachmann 1.5
755 cebix 1.9 case cscGetVideoParameters: { // Get information about specified resolution/depth
756     uint32 id = ReadMacInt32(param + csDisplayModeID);
757     uint16 mode = ReadMacInt16(param + csDepthMode);
758     D(bug(" GetVideoParameters %04x/%08x\n", mode, id));
759    
760 cebix 1.18 vector<video_mode>::const_iterator i, end = VideoModes.end();
761     for (i = VideoModes.begin(); i != end; ++i) {
762 cebix 1.9 if (DepthToAppleMode(i->depth) == mode && i->resolution_id == id) {
763     uint32 vp = ReadMacInt32(param + csVPBlockPtr);
764     WriteMacInt32(vp + vpBaseOffset, 0);
765     WriteMacInt16(vp + vpRowBytes, i->bytes_per_row);
766     WriteMacInt16(vp + vpBounds, 0);
767     WriteMacInt16(vp + vpBounds + 2, 0);
768     WriteMacInt16(vp + vpBounds + 4, i->y);
769     WriteMacInt16(vp + vpBounds + 6, i->x);
770     WriteMacInt16(vp + vpVersion, 0);
771     WriteMacInt16(vp + vpPackType, 0);
772     WriteMacInt32(vp + vpPackSize, 0);
773 cebix 1.11 WriteMacInt32(vp + vpHRes, 0x00480000); // 72 dpi
774 cebix 1.9 WriteMacInt32(vp + vpVRes, 0x00480000);
775     uint32 pix_type, pix_size, cmp_count, cmp_size, dev_type;
776     switch (i->depth) {
777     case VDEPTH_1BIT:
778     pix_type = 0; pix_size = 1;
779     cmp_count = 1; cmp_size = 1;
780     dev_type = 0; // CLUT
781     break;
782     case VDEPTH_2BIT:
783     pix_type = 0; pix_size = 2;
784     cmp_count = 1; cmp_size = 2;
785     dev_type = 0; // CLUT
786     break;
787     case VDEPTH_4BIT:
788     pix_type = 0; pix_size = 4;
789     cmp_count = 1; cmp_size = 4;
790     dev_type = 0; // CLUT
791     break;
792     case VDEPTH_8BIT:
793     pix_type = 0; pix_size = 8;
794     cmp_count = 1; cmp_size = 8;
795     dev_type = 0; // CLUT
796     break;
797     case VDEPTH_16BIT:
798     pix_type = 0x10; pix_size = 16;
799     cmp_count = 3; cmp_size = 5;
800     dev_type = 2; // direct
801     break;
802     case VDEPTH_32BIT:
803     pix_type = 0x10; pix_size = 32;
804     cmp_count = 3; cmp_size = 8;
805     dev_type = 2; // direct
806     break;
807     }
808     WriteMacInt16(vp + vpPixelType, pix_type);
809     WriteMacInt16(vp + vpPixelSize, pix_size);
810     WriteMacInt16(vp + vpCmpCount, cmp_count);
811     WriteMacInt16(vp + vpCmpSize, cmp_size);
812     WriteMacInt32(param + csPageCount, 1);
813     WriteMacInt32(param + csDeviceType, dev_type);
814     return noErr;
815     }
816     }
817     return paramErr; // specified resolution/depth not supported
818     }
819 cebix 1.1
820     default:
821 cebix 1.2 printf("WARNING: Unknown VideoDriverStatus(%d)\n", code);
822 cebix 1.1 return statusErr;
823     }
824     }