ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/video.cpp
Revision: 1.16
Committed: 2001-07-01T00:46:31Z (23 years, 5 months ago) by cebix
Branch: MAIN
Changes since 1.15: +4 -4 lines
Log Message:
- added some documentation
- VidLocal.sp -> VidLocal.slot_param
- X11 color map is loaded with ramp upon startup to avoid the annoying black
  screen during initialization

File Contents

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