ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/video.cpp
Revision: 1.19
Committed: 2001-07-01T21:09:26Z (23 years ago) by cebix
Branch: MAIN
Changes since 1.18: +21 -3 lines
Log Message:
- video_set_palette() gets passed the number of used palette entries
- video_x.cpp supports 2- and 4-bit modes on truecolor screens

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