ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/video.cpp
Revision: 1.1.1.1 (vendor branch)
Committed: 2002-02-04T16:58:13Z (22 years, 3 months ago) by cebix
Branch: cebix
CVS Tags: start
Changes since 1.1: +0 -0 lines
Log Message:
Imported sources

File Contents

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