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

# 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 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 vector<video_mode>::const_iterator i, end = VideoModes.end();
71 for (i = VideoModes.begin(); i != end; ++i) {
72 if (i->resolution_id == id)
73 return true;
74 }
75 return false;
76 }
77
78
79 /*
80 * Find specified mode (depth/resolution) (or VideoModes.end() if not found)
81 */
82
83 static vector<video_mode>::const_iterator find_mode(uint16 mode, uint32 id)
84 {
85 vector<video_mode>::const_iterator i, end = VideoModes.end();
86 for (i = VideoModes.begin(); i != end; ++i) {
87 if (i->resolution_id == id && DepthToAppleMode(i->depth) == mode)
88 return i;
89 }
90 return i;
91 }
92
93
94 /*
95 * 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, end = VideoModes.end();
102 for (i = VideoModes.begin(); i != end; ++i) {
103 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 vector<video_mode>::const_iterator i, end = VideoModes.end();
117 for (i = VideoModes.begin(); i != end; ++i) {
118 if (i->resolution_id == id) {
119 x = i->x;
120 y = i->y;
121 return;
122 }
123 }
124 }
125
126
127 /*
128 * Set palette to 50% gray
129 */
130
131 static void set_gray_palette(void)
132 {
133 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 uint8 red = (i * 256 / num), green = red, blue = red;
171 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 }
200 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 }
207 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 }
269
270
271 /*
272 * 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 * Driver Open() routine
341 */
342
343 int16 VideoDriverOpen(uint32 pb, uint32 dce)
344 {
345 D(bug("VideoDriverOpen\n"));
346
347 // 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 // Init local variables
352 VidLocal.desc = &VideoMonitor;
353 VidLocal.luminance_mapping = false;
354 VidLocal.interrupts_enabled = false;
355 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
360 // 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 VidLocal.slot_param = r.a[0];
367 D(bug("SPBlock at %08x\n", VidLocal.slot_param));
368
369 // Find and set default gamma table
370 VidLocal.gamma_table = 0;
371 VidLocal.alloc_gamma_table_size = 0;
372 set_gamma_table(0);
373
374 // Init color palette (solid gray)
375 set_gray_palette();
376 return noErr;
377 }
378
379
380 /*
381 * Driver Control() routine
382 */
383
384 int16 VideoDriverControl(uint32 pb, uint32 dce)
385 {
386 uint16 code = ReadMacInt16(pb + csCode);
387 uint32 param = ReadMacInt32(pb + csParam);
388 D(bug("VideoDriverControl %d\n", code));
389 switch (code) {
390
391 case cscSetMode: { // Set color depth
392 uint16 mode = ReadMacInt16(param + csMode);
393 D(bug(" SetMode %04x\n", mode));
394
395 // 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 if (mode != VidLocal.current_mode) {
402 vector<video_mode>::const_iterator i = find_mode(mode, VidLocal.current_id);
403 if (i == VideoModes.end())
404 return paramErr;
405 switch_mode(*i, param, dce);
406 }
407 D(bug(" base %08x\n", VidLocal.desc->mac_frame_base));
408 return noErr;
409 }
410
411 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 return controlErr;
419
420 uint32 s_pal = ReadMacInt32(param + csTable); // Source palette
421 uint8 *d_pal; // Destination palette
422 uint16 start = ReadMacInt16(param + csStart);
423 uint16 count = ReadMacInt16(param + csCount);
424 if (s_pal == 0 || count > 255)
425 return paramErr;
426
427 // 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 if (start == 0xffff) { // Indexed
448 for (uint32 i=0; i<=count; i++) {
449 d_pal = VidLocal.palette + (ReadMacInt16(s_pal) & 0xff) * 3;
450 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 if (VidLocal.luminance_mapping && !is_direct)
454 red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16;
455 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 *d_pal++ = red;
461 *d_pal++ = green;
462 *d_pal++ = blue;
463 s_pal += 8;
464 }
465 } else { // Sequential
466 if (start + count > 255)
467 return paramErr;
468 d_pal = VidLocal.palette + start * 3;
469 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 if (VidLocal.luminance_mapping && !is_direct)
474 red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16;
475 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 *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 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
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 uint32 pat = pattern[VidLocal.desc->mode.depth];
511 bool invert = (VidLocal.desc->mode.depth == VDEPTH_32BIT);
512 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 WriteMacInt32(p + x, pat);
515 if (invert)
516 pat = ~pat;
517 }
518 p += VidLocal.desc->mode.bytes_per_row;
519 pat = ~pat;
520 }
521
522 if (IsDirectMode(VidLocal.current_mode))
523 load_ramp_palette();
524
525 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 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
550 // 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 if (mode != VidLocal.current_mode || id != VidLocal.current_id) {
557 vector<video_mode>::const_iterator i = find_mode(mode, id);
558 if (i == VideoModes.end())
559 return paramErr;
560 switch_mode(*i, param, dce);
561 }
562 D(bug(" base %08x\n", VidLocal.desc->mac_frame_base));
563 return noErr;
564 }
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 default:
576 printf("WARNING: Unknown VideoDriverControl(%d)\n", code);
577 return controlErr;
578 }
579 }
580
581
582 /*
583 * Driver Status() routine
584 */
585
586 int16 VideoDriverStatus(uint32 pb, uint32 dce)
587 {
588 uint16 code = ReadMacInt16(pb + csCode);
589 uint32 param = ReadMacInt32(pb + csParam);
590 D(bug("VideoDriverStatus %d\n", code));
591 switch (code) {
592
593 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 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
603 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 WriteMacInt16(param + csPage, 1);
641 return noErr;
642
643 case cscGetBaseAddress: // Get page base address
644 D(bug(" GetBaseAddress -> %08x\n", VidLocal.desc->mac_frame_base));
645 WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base);
646 if (ReadMacInt16(param + csPage))
647 return paramErr;
648 else
649 return noErr;
650
651 case cscGetGray: // Get luminance mapping flag
652 D(bug(" GetGray -> %d\n", VidLocal.luminance_mapping));
653 WriteMacInt16(param, VidLocal.luminance_mapping ? 0x0100 : 0);
654 return noErr;
655
656 case cscGetInterrupt: // Get interrupt disable flag
657 D(bug(" GetInterrupt -> %d\n", VidLocal.interrupts_enabled));
658 WriteMacInt16(param, VidLocal.interrupts_enabled ? 0 : 0x0100);
659 return noErr;
660
661 case cscGetGamma:
662 D(bug(" GetGamma -> %08x\n", VidLocal.gamma_table));
663 WriteMacInt32(param + csGTable, VidLocal.gamma_table);
664 return noErr;
665
666 case cscGetDefaultMode: // Get default color depth
667 D(bug(" GetDefaultMode -> %04x\n", VidLocal.preferred_mode));
668 WriteMacInt16(param + csMode, VidLocal.preferred_mode);
669 return noErr;
670
671 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 WriteMacInt16(param + csMode, VidLocal.current_mode);
674 WriteMacInt32(param + csData, VidLocal.current_id);
675 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 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 WriteMacInt32(param + csDisplayComponent, 0);
686 return noErr;
687
688 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 case cscGetModeBaseAddress: // Get frame buffer base address
704 D(bug(" GetModeBaseAddress -> base %08x\n", VidLocal.desc->mac_frame_base));
705 WriteMacInt32(param + csBaseAddr, VidLocal.desc->mac_frame_base);
706 return noErr;
707
708 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 return noErr;
753 }
754
755 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 vector<video_mode>::const_iterator i, end = VideoModes.end();
761 for (i = VideoModes.begin(); i != end; ++i) {
762 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 WriteMacInt32(vp + vpHRes, 0x00480000); // 72 dpi
774 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
820 default:
821 printf("WARNING: Unknown VideoDriverStatus(%d)\n", code);
822 return statusErr;
823 }
824 }