ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/video.cpp
Revision: 1.10
Committed: 2004-12-19T09:01:04Z (19 years, 5 months ago) by gbeauche
Branch: MAIN
Changes since 1.9: +5 -5 lines
Log Message:
FindLibSymbol() returns an address in MacOS address space. Likewise for
Mac_sysalloc(). i.e. make it return an uint32.

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