ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/video.cpp
Revision: 1.7
Committed: 2004-04-13T22:22:20Z (20 years, 1 month ago) by gbeauche
Branch: MAIN
Changes since 1.6: +8 -0 lines
Log Message:
Fix DGA mode for emulated PPC targets. It currently doesn't work in native
mode as the stack is corrupted and we are jumping to garbage when moving
the mouse. Also add 1152x768 resolution from PBG4, but make timing match
the 1152x870 version.

Cleanups, further merges from Basilisk II tree.

File Contents

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