ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/video.cpp
Revision: 1.13
Committed: 2005-01-30T21:48:19Z (19 years, 3 months ago) by gbeauche
Branch: MAIN
Changes since 1.12: +1 -1 lines
Log Message:
Happy New Year 2005!

File Contents

# Content
1 /*
2 * video.cpp - Video/graphics emulation
3 *
4 * SheepShaver (C) 1997-2005 Marc Hellwig and Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 /*
22 * TODO
23 * - check for supported modes ???
24 * - window mode "hardware" cursor hotspot
25 */
26
27 #include <stdio.h>
28 #include <string.h>
29
30 #include "sysdeps.h"
31 #include "video.h"
32 #include "video_defs.h"
33 #include "main.h"
34 #include "adb.h"
35 #include "macos_util.h"
36 #include "user_strings.h"
37 #include "version.h"
38 #include "thunks.h"
39
40 #define DEBUG 0
41 #include "debug.h"
42
43
44 // Global variables
45 bool video_activated = false; // Flag: video display activated, mouse and keyboard data valid
46 uint32 screen_base = 0; // Frame buffer base address
47 int cur_mode; // Number of current video mode (index in VModes array)
48 int display_type = DIS_INVALID; // Current display type
49 rgb_color mac_pal[256];
50 uint8 remap_mac_be[256];
51 uint8 MacCursor[68] = {16, 1}; // Mac cursor image
52
53
54 bool keyfile_valid; // Flag: Keyfile is valid, enable full-screen modes
55
56
57 /*
58 * Video mode information (constructed by VideoInit())
59 */
60
61 struct VideoInfo VModes[64];
62
63
64 /*
65 * Driver local variables
66 */
67
68 VidLocals *private_data = NULL; // Pointer to driver local variables (there is only one display, so this is ok)
69
70 static long save_conf_id = APPLE_W_640x480;
71 static long save_conf_mode = APPLE_8_BIT;
72
73
74 // Function pointers of imported functions
75 typedef int16 (*iocic_ptr)(void *, int16);
76 static uint32 iocic_tvect = 0;
77 static inline int16 IOCommandIsComplete(uintptr arg1, int16 arg2)
78 {
79 return (int16)CallMacOS2(iocic_ptr, iocic_tvect, (void *)arg1, arg2);
80 }
81 typedef int16 (*vslnewis_ptr)(void *, uint32, uint32 *);
82 static uint32 vslnewis_tvect = 0;
83 static inline int16 VSLNewInterruptService(uintptr arg1, uint32 arg2, uintptr arg3)
84 {
85 return (int16)CallMacOS3(vslnewis_ptr, vslnewis_tvect, (void *)arg1, arg2, (uint32 *)arg3);
86 }
87 typedef int16 (*vsldisposeis_ptr)(uint32);
88 static uint32 vsldisposeis_tvect = 0;
89 static inline int16 VSLDisposeInterruptService(uint32 arg1)
90 {
91 return (int16)CallMacOS1(vsldisposeis_ptr, vsldisposeis_tvect, arg1);
92 }
93 typedef int16 (*vsldois_ptr)(uint32);
94 static uint32 vsldois_tvect = 0;
95 int16 VSLDoInterruptService(uint32 arg1)
96 {
97 return (int16)CallMacOS1(vsldois_ptr, vsldois_tvect, arg1);
98 }
99 typedef void (*nqdmisc_ptr)(uint32, void *);
100 static uint32 nqdmisc_tvect = 0;
101 void NQDMisc(uint32 arg1, uintptr arg2)
102 {
103 CallMacOS2(nqdmisc_ptr, nqdmisc_tvect, arg1, (void *)arg2);
104 }
105
106
107 // Prototypes
108 static int16 set_gamma(VidLocals *csSave, uint32 gamma);
109
110
111 /*
112 * Tell whether window/screen is activated or not (for mouse/keyboard polling)
113 */
114
115 bool VideoActivated(void)
116 {
117 return video_activated;
118 }
119
120
121 /*
122 * Create RGB snapshot of current screen
123 */
124
125 bool VideoSnapshot(int xsize, int ysize, uint8 *p)
126 {
127 if (display_type == DIS_WINDOW) {
128 uint8 *screen = (uint8 *)private_data->saveBaseAddr;
129 uint32 row_bytes = VModes[cur_mode].viRowBytes;
130 uint32 y2size = VModes[cur_mode].viYsize;
131 uint32 x2size = VModes[cur_mode].viXsize;
132 for (int j=0;j<ysize;j++) {
133 for (int i=0;i<xsize;i++) {
134 *p++ = mac_pal[screen[uint32(float(j)*float(y2size)/float(ysize))*row_bytes+uint32(float(i)*float(x2size)/float(xsize))]].red;
135 *p++ = mac_pal[screen[uint32(float(j)*float(y2size)/float(ysize))*row_bytes+uint32(float(i)*float(x2size)/float(xsize))]].green;
136 *p++ = mac_pal[screen[uint32(float(j)*float(y2size)/float(ysize))*row_bytes+uint32(float(i)*float(x2size)/float(xsize))]].blue;
137 }
138 }
139 return true;
140 }
141 return false;
142 }
143
144
145 /*
146 * Video driver open routine
147 */
148
149 static int16 VideoOpen(uint32 pb, VidLocals *csSave)
150 {
151 D(bug("Video Open\n"));
152
153 // Set up VidLocals
154 csSave->saveBaseAddr = screen_base;
155 csSave->saveData = VModes[cur_mode].viAppleID;// First mode ...
156 csSave->saveMode = VModes[cur_mode].viAppleMode;
157 csSave->savePage = 0;
158 csSave->saveVidParms = 0; // Add the right table
159 csSave->luminanceMapping = false;
160 csSave->cursorX = 0;
161 csSave->cursorY = 0;
162 csSave->cursorVisible = 0;
163 csSave->cursorSet = 0;
164
165 // Find and set default gamma table
166 csSave->gammaTable = 0;
167 csSave->maxGammaTableSize = 0;
168 set_gamma(csSave, 0);
169
170 // Install and activate interrupt service
171 SheepVar32 theServiceID = 0;
172 VSLNewInterruptService(csSave->regEntryID, FOURCC('v','b','l',' '), theServiceID.addr());
173 csSave->vslServiceID = theServiceID.value();
174 D(bug(" Interrupt ServiceID %08lx\n", csSave->vslServiceID));
175 csSave->interruptsEnabled = true;
176
177 return noErr;
178 }
179
180
181 /*
182 * Video driver control routine
183 */
184
185 static bool allocate_gamma_table(VidLocals *csSave, uint32 size)
186 {
187 if (size > csSave->maxGammaTableSize) {
188 if (csSave->gammaTable) {
189 Mac_sysfree(csSave->gammaTable);
190 csSave->gammaTable = 0;
191 csSave->maxGammaTableSize = 0;
192 }
193 if ((csSave->gammaTable = Mac_sysalloc(size)) == 0)
194 return false;
195 csSave->maxGammaTableSize = size;
196 }
197 return true;
198 }
199
200 static int16 set_gamma(VidLocals *csSave, uint32 gamma)
201 {
202 return paramErr;
203
204 if (gamma == 0) { // Build linear ramp, 256 entries
205
206 // Allocate new table, if necessary
207 if (!allocate_gamma_table(csSave, SIZEOF_GammaTbl + 256))
208 return memFullErr;
209
210 // Initialize header
211 WriteMacInt16(csSave->gammaTable + gVersion, 0); // A version 0 style of the GammaTbl structure
212 WriteMacInt16(csSave->gammaTable + gType, 0); // Frame buffer hardware invariant
213 WriteMacInt16(csSave->gammaTable + gFormulaSize, 0); // No formula data, just correction data
214 WriteMacInt16(csSave->gammaTable + gChanCnt, 1); // Apply same correction to Red, Green, & Blue
215 WriteMacInt16(csSave->gammaTable + gDataCnt, 256); // gDataCnt == 2^^gDataWidth
216 WriteMacInt16(csSave->gammaTable + gDataWidth, 8); // 8 bits of significant data per entry
217
218 // Build the linear ramp
219 uint32 p = csSave->gammaTable + gFormulaData;
220 for (int i=0; i<256; i++)
221 WriteMacInt8(p + i, i);
222
223 } else { // User-supplied gamma table
224
225 // Validate header
226 if (ReadMacInt16(gamma + gVersion) != 0)
227 return paramErr;
228 if (ReadMacInt16(gamma + gType) != 0)
229 return paramErr;
230 int chan_cnt = ReadMacInt16(gamma + gChanCnt);
231 if (chan_cnt != 1 && chan_cnt != 3)
232 return paramErr;
233 int data_width = ReadMacInt16(gamma + gDataWidth);
234 if (data_width > 8)
235 return paramErr;
236 int data_cnt = ReadMacInt16(gamma + gDataWidth);
237 if (data_cnt != (1 << data_width))
238 return paramErr;
239
240 // Allocate new table, if necessary
241 int size = SIZEOF_GammaTbl + ReadMacInt16(gamma + gFormulaSize) + chan_cnt * data_cnt;
242 if (!allocate_gamma_table(csSave, size))
243 return memFullErr;
244
245 // Copy table
246 Mac2Mac_memcpy(csSave->gammaTable, gamma, size);
247 }
248 return noErr;
249 }
250
251 static int16 VideoControl(uint32 pb, VidLocals *csSave)
252 {
253 int16 code = ReadMacInt16(pb + csCode);
254 D(bug("VideoControl %d: ", code));
255 uint32 param = ReadMacInt32(pb + csParam);
256 switch (code) {
257
258 case cscReset: // VidReset
259 D(bug("VidReset\n"));
260 return controlErr;
261
262 case cscKillIO: // VidKillIO
263 D(bug("VidKillIO\n"));
264 return controlErr;
265
266 case cscSetMode: // SetVidMode
267 D(bug("SetVidMode\n"));
268 D(bug("mode:%04x page:%04x \n", ReadMacInt16(param + csMode),
269 ReadMacInt16(param + csPage)));
270 WriteMacInt32(param + csData, csSave->saveData);
271 return video_mode_change(csSave, param);
272
273 case cscSetEntries: { // SetEntries
274 D(bug("SetEntries\n"));
275 if (VModes[cur_mode].viAppleMode > APPLE_8_BIT) return controlErr;
276 uint32 s_pal = ReadMacInt32(param + csTable);
277 uint16 start = ReadMacInt16(param + csStart);
278 uint16 count = ReadMacInt16(param + csCount);
279 if (s_pal == 0 || count > 256) return controlErr;
280
281 // Preparations for gamma correction
282 bool do_gamma = false;
283 uint8 *red_gamma = NULL;
284 uint8 *green_gamma = NULL;
285 uint8 *blue_gamma = NULL;
286 int gamma_data_width = 0;
287 if (csSave->gammaTable) {
288 #ifdef __BEOS__
289 // Windows are gamma-corrected by BeOS
290 const bool can_do_gamma = (display_type == DIS_SCREEN);
291 #else
292 const bool can_do_gamma = true;
293 #endif
294 if (can_do_gamma) {
295 uint32 gamma_table = csSave->gammaTable;
296 red_gamma = Mac2HostAddr(gamma_table + gFormulaData + ReadMacInt16(gamma_table + gFormulaSize));
297 int chan_cnt = ReadMacInt16(gamma_table + gChanCnt);
298 if (chan_cnt == 1)
299 green_gamma = blue_gamma = red_gamma;
300 else {
301 int ofs = ReadMacInt16(gamma_table + gDataCnt);
302 green_gamma = red_gamma + ofs;
303 blue_gamma = green_gamma + ofs;
304 }
305 gamma_data_width = ReadMacInt16(gamma_table + gDataWidth);
306 do_gamma = true;
307 }
308 }
309
310 // Set palette
311 rgb_color *d_pal;
312 if (start == 0xffff) { // Indexed
313 for (int i=0; i<=count; i++) {
314 d_pal = mac_pal + (ReadMacInt16(s_pal + csValue) & 0xff);
315 uint8 red = (uint16)ReadMacInt16(s_pal + csRed) >> 8;
316 uint8 green = (uint16)ReadMacInt16(s_pal + csGreen) >> 8;
317 uint8 blue = (uint16)ReadMacInt16(s_pal + csBlue) >> 8;
318 if (csSave->luminanceMapping)
319 red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16;
320 if (do_gamma) {
321 red = red_gamma[red >> (8 - gamma_data_width)];
322 green = green_gamma[green >> (8 - gamma_data_width)];
323 blue = blue_gamma[blue >> (8 - gamma_data_width)];
324 }
325 (*d_pal).red = red;
326 (*d_pal).green = green;
327 (*d_pal).blue = blue;
328 s_pal += 8;
329 }
330 } else { // Sequential
331 d_pal = mac_pal + start;
332 for (int i=0; i<=count; i++) {
333 uint8 red = (uint16)ReadMacInt16(s_pal + csRed) >> 8;
334 uint8 green = (uint16)ReadMacInt16(s_pal + csGreen) >> 8;
335 uint8 blue = (uint16)ReadMacInt16(s_pal + csBlue) >> 8;
336 if (csSave->luminanceMapping)
337 red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16;
338 if (do_gamma) {
339 red = red_gamma[red >> (8 - gamma_data_width)];
340 green = green_gamma[green >> (8 - gamma_data_width)];
341 blue = blue_gamma[blue >> (8 - gamma_data_width)];
342 }
343 (*d_pal).red = red;
344 (*d_pal).green = green;
345 (*d_pal).blue = blue;
346 d_pal++;
347 s_pal += 8;
348 }
349 }
350 video_set_palette();
351 return noErr;
352 }
353
354 case cscSetGamma: { // SetGamma
355 uint32 user_table = ReadMacInt32(param + csGTable);
356 D(bug("SetGamma %08x\n", user_table));
357 return set_gamma(csSave, ReadMacInt32(user_table));
358 }
359
360 case cscGrayPage: { // GrayPage
361 D(bug("GrayPage %d\n", ReadMacInt16(param + csPage)));
362 if (ReadMacInt16(param + csPage))
363 return paramErr;
364
365 uint32 pattern[6] = {
366 0xaaaaaaaa, // 1 bpp
367 0xcccccccc, // 2 bpp
368 0xf0f0f0f0, // 4 bpp
369 0xff00ff00, // 8 bpp
370 0xffff0000, // 16 bpp
371 0xffffffff // 32 bpp
372 };
373 uint32 p = csSave->saveBaseAddr;
374 uint32 pat = pattern[VModes[cur_mode].viAppleMode - APPLE_1_BIT];
375 bool invert = (VModes[cur_mode].viAppleMode == APPLE_32_BIT);
376 for (uint32 y=0; y<VModes[cur_mode].viYsize; y++) {
377 for (uint32 x=0; x<VModes[cur_mode].viRowBytes; x+=4) {
378 WriteMacInt32(p + x, pat);
379 if (invert)
380 pat = ~pat;
381 }
382 p += VModes[cur_mode].viRowBytes;
383 pat = ~pat;
384 }
385 return noErr;
386 }
387
388 case cscSetGray: // SetGray
389 D(bug("SetGray %02x\n", ReadMacInt8(param)));
390 csSave->luminanceMapping = ReadMacInt8(param);
391 return noErr;
392
393 case cscSetInterrupt: // SetInterrupt
394 D(bug("SetInterrupt\n"));
395 csSave->interruptsEnabled = !ReadMacInt8(param);
396 return noErr;
397
398 case cscDirectSetEntries: // DirectSetEntries
399 D(bug("DirectSetEntries\n"));
400 return controlErr;
401
402 case cscSetDefaultMode: // SetDefaultMode
403 D(bug("SetDefaultMode\n"));
404 return controlErr;
405
406 case cscSwitchMode:
407 D(bug("cscSwitchMode (Display Manager support) \nMode:%02x ID:%04x Page:%d\n",
408 ReadMacInt16(param + csMode), ReadMacInt32(param + csData), ReadMacInt16(param + csPage)));
409 return video_mode_change(csSave, param);
410
411 case cscSavePreferredConfiguration:
412 D(bug("SavePreferredConfiguration\n"));
413 save_conf_id = ReadMacInt32(param + csData);
414 save_conf_mode = ReadMacInt16(param + csMode);
415 return noErr;
416
417 case cscSetHardwareCursor: {
418 // D(bug("SetHardwareCursor\n"));
419 csSave->cursorSet = false;
420 bool changed = false;
421
422 // Get cursor data even on a screen, to set the right cursor image when switching back to a window
423 // Image
424 uint32 cursor = ReadMacInt32(param); // Pointer to CursorImage
425 uint32 pmhandle = ReadMacInt32(cursor + ciCursorPixMap);
426 if (pmhandle == 0 || ReadMacInt32(pmhandle) == 0)
427 return controlErr;
428 uint32 pixmap = ReadMacInt32(pmhandle);
429 if (memcmp(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32)) {
430 memcpy(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32);
431 changed = true;
432 }
433
434 // Mask
435 uint32 bmhandle = ReadMacInt32(cursor + ciCursorBitMask);
436 if (bmhandle == 0 || ReadMacInt32(bmhandle) == 0)
437 return controlErr;
438 uint32 bitmap = ReadMacInt32(bmhandle);
439 if (memcmp(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32)) {
440 memcpy(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32);
441 changed = true;
442 }
443
444 // Hotspot (!! this doesn't work)
445 MacCursor[2] = ReadMacInt8(0x885);
446 MacCursor[3] = ReadMacInt8(0x887);
447
448 // Set new cursor image
449 if (!video_can_change_cursor())
450 return controlErr;
451 if (changed)
452 video_set_cursor();
453
454 csSave->cursorSet = true;
455 return noErr;
456 }
457
458 case cscDrawHardwareCursor:
459 // D(bug("DrawHardwareCursor\n"));
460 csSave->cursorX = ReadMacInt32(param + csCursorX);
461 csSave->cursorY = ReadMacInt32(param + csCursorY);
462 csSave->cursorVisible = ReadMacInt32(param + csCursorVisible);
463 return noErr;
464
465 case 43: { // Driver Gestalt
466 uint32 sel = ReadMacInt32(pb + csParam);
467 D(bug(" driver gestalt %c%c%c%c\n", sel >> 24, sel >> 16, sel >> 8, sel));
468 switch (sel) {
469 case FOURCC('v','e','r','s'):
470 WriteMacInt32(pb + csParam + 4, 0x01008000);
471 break;
472 case FOURCC('i','n','t','f'):
473 WriteMacInt32(pb + csParam + 4, FOURCC('c','a','r','d'));
474 break;
475 case FOURCC('s','y','n','c'):
476 WriteMacInt32(pb + csParam + 4, 0x01000000);
477 break;
478 default:
479 return statusErr;
480 };
481 return noErr;
482 }
483
484 default:
485 D(bug(" unknown control code %d\n", code));
486 return controlErr;
487 }
488 }
489
490
491 /*
492 * Video driver status routine
493 */
494
495 // Search for given AppleID in mode table
496 static bool has_mode(uint32 id)
497 {
498 VideoInfo *p = VModes;
499 while (p->viType != DIS_INVALID) {
500 if (p->viAppleID == id)
501 return true;
502 p++;
503 }
504 return false;
505 }
506
507 // Find maximum depth for given AppleID
508 static uint32 max_depth(uint32 id)
509 {
510 uint32 max = APPLE_1_BIT;
511 VideoInfo *p = VModes;
512 while (p->viType != DIS_INVALID) {
513 if (p->viAppleID == id && p->viAppleMode > max)
514 max = p->viAppleMode;
515 p++;
516 }
517 return max;
518 }
519
520 static int16 VideoStatus(uint32 pb, VidLocals *csSave)
521 {
522 int16 code = ReadMacInt16(pb + csCode);
523 D(bug("VideoStatus %d: ", code));
524 uint32 param = ReadMacInt32(pb + csParam);
525 switch (code) {
526
527 case cscGetMode: // GetMode
528 D(bug("GetMode\n"));
529 WriteMacInt32(param + csBaseAddr, csSave->saveBaseAddr);
530 WriteMacInt16(param + csMode, csSave->saveMode);
531 WriteMacInt16(param + csPage, csSave->savePage);
532 D(bug("return: mode:%04x page:%04x ", ReadMacInt16(param + csMode),
533 ReadMacInt16(param + csPage)));
534 D(bug("base adress %08lx\n", ReadMacInt32(param + csBaseAddr)));
535 return noErr;
536
537 case cscGetEntries: { // GetEntries
538 D(bug("GetEntries\n"));
539 uint32 d_pal = ReadMacInt32(param + csTable);
540 uint16 start = ReadMacInt16(param + csStart);
541 uint16 count = ReadMacInt16(param + csCount);
542 rgb_color *s_pal;
543 if ((VModes[cur_mode].viAppleMode == APPLE_32_BIT)||
544 (VModes[cur_mode].viAppleMode == APPLE_16_BIT)) {
545 D(bug("ERROR: GetEntries in direct mode \n"));
546 return statusErr;
547 }
548
549 if (start == 0xffff) { // Indexed
550 for (uint16 i=0;i<count;i++) {
551 s_pal = mac_pal + (ReadMacInt16(d_pal + csValue) & 0xff);
552 uint8 red = (*s_pal).red;
553 uint8 green = (*s_pal).green;
554 uint8 blue = (*s_pal).blue;
555 WriteMacInt16(d_pal + csRed, red * 0x0101);
556 WriteMacInt16(d_pal + csGreen, green * 0x0101);
557 WriteMacInt16(d_pal + csBlue, blue * 0x0101);
558 d_pal += 8;
559 }
560 } else { // Sequential
561 if (start + count > 255)
562 return paramErr;
563 s_pal = mac_pal + start;
564 for (uint16 i=0;i<count;i++) {
565 uint8 red = (*s_pal).red;
566 uint8 green = (*s_pal).green;
567 uint8 blue = (*s_pal).blue;
568 s_pal++;
569 WriteMacInt16(d_pal + csRed, red * 0x0101);
570 WriteMacInt16(d_pal + csGreen, green * 0x0101);
571 WriteMacInt16(d_pal + csBlue, blue * 0x0101);
572 d_pal += 8;
573 }
574 };
575 return noErr;
576 }
577
578 case cscGetPageCnt: // GetPage
579 D(bug("GetPage\n"));
580 WriteMacInt16(param + csPage, 1);
581 return noErr;
582
583 case cscGetPageBase: // GetPageBase
584 D(bug("GetPageBase\n"));
585 WriteMacInt32(param + csBaseAddr, csSave->saveBaseAddr);
586 return noErr;
587
588 case cscGetGray: // GetGray
589 D(bug("GetGray\n"));
590 WriteMacInt8(param, csSave->luminanceMapping ? 1 : 0);
591 return noErr;
592
593 case cscGetInterrupt: // GetInterrupt
594 D(bug("GetInterrupt\n"));
595 WriteMacInt8(param, csSave->interruptsEnabled ? 0 : 1);
596 return noErr;
597
598 case cscGetGamma: // GetGamma
599 D(bug("GetGamma\n"));
600 WriteMacInt32(param, (uint32)csSave->gammaTable);
601 return statusErr;
602
603 case cscGetDefaultMode: // GetDefaultMode
604 D(bug("GetDefaultMode\n"));
605 return statusErr;
606
607 case cscGetCurMode: // GetCurMode
608 D(bug("GetCurMode\n"));
609 WriteMacInt16(param + csMode, csSave->saveMode);
610 WriteMacInt32(param + csData, csSave->saveData);
611 WriteMacInt16(param + csPage, csSave->savePage);
612 WriteMacInt32(param + csBaseAddr, csSave->saveBaseAddr);
613
614 D(bug("return: mode:%04x ID:%08lx page:%04x ", ReadMacInt16(param + csMode),
615 ReadMacInt32(param + csData), ReadMacInt16(param + csPage)));
616 D(bug("base adress %08lx\n", ReadMacInt32(param + csBaseAddr)));
617 return noErr;
618
619 case cscGetConnection: // GetConnection
620 D(bug("GetConnection\n"));
621 WriteMacInt16(param + csDisplayType, kMultiModeCRT3Connect);
622 WriteMacInt8(param + csConnectTaggedType, 6);
623 WriteMacInt8(param + csConnectTaggedData, 0x23);
624 WriteMacInt32(param + csConnectFlags, (1<<kAllModesValid)|(1<<kAllModesSafe));
625 WriteMacInt32(param + csDisplayComponent, 0);
626 return noErr;
627
628 case cscGetModeBaseAddress:
629 D(bug("GetModeBaseAddress (obsolete !) \n"));
630 return statusErr;
631
632 case cscGetPreferredConfiguration:
633 D(bug("GetPreferredConfiguration \n"));
634 WriteMacInt16(param + csMode, save_conf_mode);
635 WriteMacInt32(param + csData, save_conf_id);
636 return noErr;
637
638 case cscGetNextResolution: {
639 D(bug("GetNextResolution \n"));
640 int work_id = ReadMacInt32(param + csPreviousDisplayModeID);
641 switch (work_id) {
642 case kDisplayModeIDCurrent:
643 work_id = csSave->saveData;
644 break;
645 case kDisplayModeIDFindFirstResolution:
646 work_id = APPLE_ID_MIN;
647 while (!has_mode(work_id))
648 work_id ++;
649 break;
650 default:
651 if (!has_mode(work_id))
652 return paramErr;
653 work_id++;
654 while (!has_mode(work_id)) {
655 work_id++;
656 if (work_id > APPLE_ID_MAX) {
657 WriteMacInt32(param + csRIDisplayModeID, kDisplayModeIDNoMoreResolutions);
658 return noErr;
659 }
660 }
661 break;
662 }
663 WriteMacInt32(param + csRIDisplayModeID, work_id);
664 WriteMacInt16(param + csMaxDepthMode, max_depth(work_id));
665 switch (work_id) {
666 case APPLE_640x480:
667 WriteMacInt32(param + csHorizontalPixels, 640);
668 WriteMacInt32(param + csVerticalLines, 480);
669 WriteMacInt32(param + csRefreshRate, 75<<16);
670 break;
671 case APPLE_W_640x480:
672 WriteMacInt32(param + csHorizontalPixels, 640);
673 WriteMacInt32(param + csVerticalLines, 480);
674 WriteMacInt32(param + csRefreshRate, 60<<16);
675 break;
676 case APPLE_800x600:
677 WriteMacInt32(param + csHorizontalPixels, 800);
678 WriteMacInt32(param + csVerticalLines, 600);
679 WriteMacInt32(param + csRefreshRate, 75<<16);
680 break;
681 case APPLE_W_800x600:
682 WriteMacInt32(param + csHorizontalPixels, 800);
683 WriteMacInt32(param + csVerticalLines, 600);
684 WriteMacInt32(param + csRefreshRate, 60<<16);
685 break;
686 case APPLE_1024x768:
687 WriteMacInt32(param + csHorizontalPixels, 1024);
688 WriteMacInt32(param + csVerticalLines, 768);
689 WriteMacInt32(param + csRefreshRate, 75<<16);
690 break;
691 case APPLE_1152x768:
692 WriteMacInt32(param + csHorizontalPixels, 1152);
693 WriteMacInt32(param + csVerticalLines, 768);
694 WriteMacInt32(param + csRefreshRate, 75<<16);
695 break;
696 case APPLE_1152x900:
697 WriteMacInt32(param + csHorizontalPixels, 1152);
698 WriteMacInt32(param + csVerticalLines, 900);
699 WriteMacInt32(param + csRefreshRate, 75<<16);
700 break;
701 case APPLE_1280x1024:
702 WriteMacInt32(param + csHorizontalPixels, 1280);
703 WriteMacInt32(param + csVerticalLines, 1024);
704 WriteMacInt32(param + csRefreshRate, 75<<16);
705 break;
706 case APPLE_1600x1200:
707 WriteMacInt32(param + csHorizontalPixels, 1600);
708 WriteMacInt32(param + csVerticalLines, 1200);
709 WriteMacInt32(param + csRefreshRate, 75<<16);
710 break;
711 }
712 return noErr;
713 }
714
715 case cscGetVideoParameters: // GetVideoParameters
716 D(bug("GetVideoParameters ID:%08lx Depth:%04x\n",
717 ReadMacInt32(param + csDisplayModeID),
718 ReadMacInt16(param + csDepthMode)));
719
720 // find right video mode
721 for (int i=0; VModes[i].viType!=DIS_INVALID; i++) {
722 if ((ReadMacInt16(param + csDepthMode) == VModes[i].viAppleMode) &&
723 (ReadMacInt32(param + csDisplayModeID) == VModes[i].viAppleID)) {
724 uint32 vpb = ReadMacInt32(param + csVPBlockPtr);
725 WriteMacInt32(vpb + vpBaseOffset, 0);
726 WriteMacInt16(vpb + vpRowBytes, VModes[i].viRowBytes);
727 WriteMacInt16(vpb + vpBounds, 0);
728 WriteMacInt16(vpb + vpBounds + 2, 0);
729 WriteMacInt16(vpb + vpBounds + 4, VModes[i].viYsize);
730 WriteMacInt16(vpb + vpBounds + 6, VModes[i].viXsize);
731 WriteMacInt16(vpb + vpVersion, 0); // Pixel Map version number
732 WriteMacInt16(vpb + vpPackType, 0);
733 WriteMacInt32(vpb + vpPackSize, 0);
734 WriteMacInt32(vpb + vpHRes, 0x00480000); // horiz res of the device (ppi)
735 WriteMacInt32(vpb + vpVRes, 0x00480000); // vert res of the device (ppi)
736 switch (VModes[i].viAppleMode) {
737 case APPLE_1_BIT:
738 WriteMacInt16(vpb + vpPixelType, 0);
739 WriteMacInt16(vpb + vpPixelSize, 1);
740 WriteMacInt16(vpb + vpCmpCount, 1);
741 WriteMacInt16(vpb + vpCmpSize, 1);
742 WriteMacInt32(param + csDeviceType, 0); // CLUT
743 break;
744 case APPLE_2_BIT:
745 WriteMacInt16(vpb + vpPixelType, 0);
746 WriteMacInt16(vpb + vpPixelSize, 2);
747 WriteMacInt16(vpb + vpCmpCount, 1);
748 WriteMacInt16(vpb + vpCmpSize, 2);
749 WriteMacInt32(param + csDeviceType, 0); // CLUT
750 break;
751 case APPLE_4_BIT:
752 WriteMacInt16(vpb + vpPixelType, 0);
753 WriteMacInt16(vpb + vpPixelSize, 4);
754 WriteMacInt16(vpb + vpCmpCount, 1);
755 WriteMacInt16(vpb + vpCmpSize, 4);
756 WriteMacInt32(param + csDeviceType, 0); // CLUT
757 break;
758 case APPLE_8_BIT:
759 WriteMacInt16(vpb + vpPixelType, 0);
760 WriteMacInt16(vpb + vpPixelSize, 8);
761 WriteMacInt16(vpb + vpCmpCount, 1);
762 WriteMacInt16(vpb + vpCmpSize, 8);
763 WriteMacInt32(param + csDeviceType, 0); // CLUT
764 break;
765 case APPLE_16_BIT:
766 WriteMacInt16(vpb + vpPixelType, 0x10);
767 WriteMacInt16(vpb + vpPixelSize, 16);
768 WriteMacInt16(vpb + vpCmpCount, 3);
769 WriteMacInt16(vpb + vpCmpSize, 5);
770 WriteMacInt32(param + csDeviceType, 2); // DIRECT
771 break;
772 case APPLE_32_BIT:
773 WriteMacInt16(vpb + vpPixelType, 0x10);
774 WriteMacInt16(vpb + vpPixelSize, 32);
775 WriteMacInt16(vpb + vpCmpCount, 3);
776 WriteMacInt16(vpb + vpCmpSize, 8);
777 WriteMacInt32(param + csDeviceType, 2); // DIRECT
778 break;
779 }
780 WriteMacInt32(param + csPageCount, 1);
781 return noErr;
782 }
783 }
784 return paramErr;
785
786 case cscGetModeTiming:
787 D(bug("GetModeTiming mode %08lx\n", ReadMacInt32(param + csTimingMode)));
788 WriteMacInt32(param + csTimingFormat, kDeclROMtables);
789 WriteMacInt32(param + csTimingFlags, (1<<kModeValid)|(1<<kModeSafe)|(1<<kShowModeNow)); // Mode valid, safe, default and shown in Monitors panel
790 for (int i=0; VModes[i].viType!=DIS_INVALID; i++) {
791 if (ReadMacInt32(param + csTimingMode) == VModes[i].viAppleID) {
792 uint32 timing = timingUnknown;
793 uint32 flags = (1<<kModeValid) | (1<<kShowModeNow);
794 switch (VModes[i].viAppleID) {
795 case APPLE_640x480:
796 timing = timingVESA_640x480_75hz;
797 flags |= (1<<kModeSafe);
798 break;
799 case APPLE_W_640x480:
800 timing = timingVESA_640x480_60hz;
801 flags |= (1<<kModeSafe);
802 break;
803 case APPLE_800x600:
804 timing = timingVESA_800x600_75hz;
805 flags |= (1<<kModeSafe);
806 break;
807 case APPLE_W_800x600:
808 timing = timingVESA_800x600_60hz;
809 flags |= (1<<kModeSafe);
810 break;
811 case APPLE_1024x768:
812 timing = timingVESA_1024x768_75hz;
813 break;
814 case APPLE_1152x768:
815 timing = timingApple_1152x870_75hz; // FIXME
816 break;
817 case APPLE_1152x900:
818 timing = timingApple_1152x870_75hz;
819 break;
820 case APPLE_1280x1024:
821 timing = timingVESA_1280x960_75hz;
822 break;
823 case APPLE_1600x1200:
824 timing = timingVESA_1600x1200_75hz;
825 break;
826 default:
827 timing = timingUnknown;
828 break;
829 }
830 WriteMacInt32(param + csTimingData, timing);
831 WriteMacInt32(param + csTimingFlags, flags);
832 return noErr;
833 }
834 }
835 return paramErr;
836
837 case cscSupportsHardwareCursor:
838 D(bug("SupportsHardwareCursor\n"));
839 WriteMacInt32(param, 1);
840 return noErr;
841
842 case cscGetHardwareCursorDrawState:
843 D(bug("GetHardwareCursorDrawState\n"));
844 WriteMacInt32(param + csCursorX, csSave->cursorX);
845 WriteMacInt32(param + csCursorY, csSave->cursorY);
846 WriteMacInt32(param + csCursorVisible, csSave->cursorVisible);
847 WriteMacInt32(param + csCursorSet, csSave->cursorSet);
848 return noErr;
849
850 default:
851 D(bug(" unknown status code %d\n", code));
852 return statusErr;
853 }
854 }
855
856
857 /*
858 * Video driver close routine
859 */
860
861 static int16 VideoClose(uint32 pb, VidLocals *csSave)
862 {
863 D(bug("VideoClose\n"));
864
865 // Delete interrupt service
866 csSave->interruptsEnabled = false;
867 VSLDisposeInterruptService(csSave->vslServiceID);
868
869 return noErr;
870 }
871
872
873 /*
874 * Native (PCI) driver entry
875 */
876
877 int16 VideoDoDriverIO(uint32 spaceID, uint32 commandID, uint32 commandContents, uint32 commandCode, uint32 commandKind)
878 {
879 // D(bug("VideoDoDriverIO space %08x, command %08x, contents %08x, code %d, kind %d\n", spaceID, commandID, commandContents, commandCode, commandKind));
880 int16 err = noErr;
881
882 switch (commandCode) {
883 case kInitializeCommand:
884 case kReplaceCommand:
885 if (private_data != NULL) { // Might be left over from a reboot
886 if (private_data->gammaTable)
887 Mac_sysfree(private_data->gammaTable);
888 if (private_data->regEntryID)
889 Mac_sysfree(private_data->regEntryID);
890 }
891 delete private_data;
892
893 iocic_tvect = FindLibSymbol("\021DriverServicesLib", "\023IOCommandIsComplete");
894 D(bug("IOCommandIsComplete TVECT at %08lx\n", iocic_tvect));
895 if (iocic_tvect == 0) {
896 printf("FATAL: VideoDoDriverIO(): Can't find IOCommandIsComplete()\n");
897 err = -1;
898 break;
899 }
900 vslnewis_tvect = FindLibSymbol("\020VideoServicesLib", "\026VSLNewInterruptService");
901 D(bug("VSLNewInterruptService TVECT at %08lx\n", vslnewis_tvect));
902 if (vslnewis_tvect == 0) {
903 printf("FATAL: VideoDoDriverIO(): Can't find VSLNewInterruptService()\n");
904 err = -1;
905 break;
906 }
907 vsldisposeis_tvect = FindLibSymbol("\020VideoServicesLib", "\032VSLDisposeInterruptService");
908 D(bug("VSLDisposeInterruptService TVECT at %08lx\n", vsldisposeis_tvect));
909 if (vsldisposeis_tvect == 0) {
910 printf("FATAL: VideoDoDriverIO(): Can't find VSLDisposeInterruptService()\n");
911 err = -1;
912 break;
913 }
914 vsldois_tvect = FindLibSymbol("\020VideoServicesLib", "\025VSLDoInterruptService");
915 D(bug("VSLDoInterruptService TVECT at %08lx\n", vsldois_tvect));
916 if (vsldois_tvect == 0) {
917 printf("FATAL: VideoDoDriverIO(): Can't find VSLDoInterruptService()\n");
918 err = -1;
919 break;
920 }
921 nqdmisc_tvect = FindLibSymbol("\014InterfaceLib", "\007NQDMisc");
922 D(bug("NQDMisc TVECT at %08lx\n", nqdmisc_tvect));
923 if (nqdmisc_tvect == 0) {
924 printf("FATAL: VideoDoDriverIO(): Can't find NQDMisc()\n");
925 err = -1;
926 break;
927 }
928
929 private_data = new VidLocals;
930 private_data->gammaTable = 0;
931 private_data->regEntryID = Mac_sysalloc(sizeof(RegEntryID));
932 if (private_data->regEntryID == 0) {
933 printf("FATAL: VideoDoDriverIO(): Can't allocate service owner\n");
934 err = -1;
935 break;
936 }
937 Mac2Mac_memcpy(private_data->regEntryID, commandContents + 2, 16); // DriverInitInfo.deviceEntry
938 private_data->interruptsEnabled = false; // Disable interrupts
939 break;
940
941 case kFinalizeCommand:
942 case kSupersededCommand:
943 if (private_data != NULL) {
944 if (private_data->gammaTable)
945 Mac_sysfree(private_data->gammaTable);
946 if (private_data->regEntryID)
947 Mac_sysfree(private_data->regEntryID);
948 }
949 delete private_data;
950 private_data = NULL;
951 break;
952
953 case kOpenCommand:
954 err = VideoOpen(commandContents, private_data);
955 break;
956
957 case kCloseCommand:
958 err = VideoClose(commandContents, private_data);
959 break;
960
961 case kControlCommand:
962 err = VideoControl(commandContents, private_data);
963 break;
964
965 case kStatusCommand:
966 err = VideoStatus(commandContents, private_data);
967 break;
968
969 case kReadCommand:
970 case kWriteCommand:
971 break;
972
973 case kKillIOCommand:
974 err = abortErr;
975 break;
976
977 default:
978 err = paramErr;
979 break;
980 }
981
982 if (commandKind == kImmediateIOCommandKind)
983 return err;
984 else
985 return IOCommandIsComplete(commandID, err);
986 }