ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/video.cpp
Revision: 1.5
Committed: 2004-01-12T15:37:19Z (20 years, 4 months ago) by cebix
Branch: MAIN
Changes since 1.4: +1 -1 lines
Log Message:
Happy New Year! :)

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 ColorSpec *s_pal = (ColorSpec *)Mac2HostAddr(ReadMacInt32(param + csTable));
291 int16 start = ReadMacInt16(param + csStart);
292 int16 count = ReadMacInt16(param + csCount);
293 if (s_pal == NULL || 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 == -1) { // Indexed
317 for (int i=0; i<=count; i++) {
318 d_pal = &(mac_pal[(*s_pal).value]);
319 uint8 red = (*s_pal).red >> 8;
320 uint8 green = (*s_pal).green >> 8;
321 uint8 blue = (*s_pal).blue >> 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++;
333 }
334 } else { // Sequential
335 d_pal = &(mac_pal[start]);
336 for (int i=0; i<=count; i++) {
337 uint8 red = (*s_pal).red >> 8;
338 uint8 green = (*s_pal).green >> 8;
339 uint8 blue = (*s_pal).blue >> 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++; s_pal++;
351 }
352 }
353 video_set_palette();
354 return noErr;
355 }
356
357 case cscSetGamma: // SetGamma
358 D(bug("SetGamma\n"));
359 return set_gamma(csSave, ReadMacInt32(param));
360
361 case cscGrayPage: { // GrayPage
362 D(bug("GrayPage\n"));
363 uint32 *screen = (uint32 *)csSave->saveBaseAddr;
364 uint32 pattern;
365 uint32 row_bytes = VModes[cur_mode].viRowBytes;
366 switch (VModes[cur_mode].viAppleMode) {
367 case APPLE_8_BIT:
368 pattern=0xff00ff00;
369 for (int i=0;i<VModes[cur_mode].viYsize;i++) {
370 for (int j=0;j<(VModes[cur_mode].viXsize>>2);j++)
371 screen[j] = pattern;
372 pattern = ~pattern;
373 screen = (uint32 *)((uint32)screen + row_bytes);
374 }
375 break;
376 case APPLE_16_BIT:
377 pattern=0xffff0000;
378 for (int i=0;i<VModes[cur_mode].viYsize;i++) {
379 for (int j=0;j<(VModes[cur_mode].viXsize>>1);j++)
380 screen[j]=pattern;
381 pattern = ~pattern;
382 screen = (uint32 *)((uint32)screen + row_bytes);
383 }
384 break;
385 case APPLE_32_BIT:
386 pattern=0xffffffff;
387 for (int i=0;i<VModes[cur_mode].viYsize;i++) {
388 for (int j=0;j<VModes[cur_mode].viXsize;j++) {
389 screen[j]=pattern;
390 pattern = ~pattern;
391 }
392 screen = (uint32 *)((uint32)screen + row_bytes);
393 }
394 break;
395 }
396 return noErr;
397 }
398
399 case cscSetGray: // SetGray
400 D(bug("SetGray %02x\n", ReadMacInt8(param)));
401 csSave->luminanceMapping = ReadMacInt8(param);
402 return noErr;
403
404 case cscSetInterrupt: // SetInterrupt
405 D(bug("SetInterrupt\n"));
406 csSave->interruptsEnabled = !ReadMacInt8(param);
407 return noErr;
408
409 case cscDirectSetEntries: // DirectSetEntries
410 D(bug("DirectSetEntries\n"));
411 return controlErr;
412
413 case cscSetDefaultMode: // SetDefaultMode
414 D(bug("SetDefaultMode\n"));
415 return controlErr;
416
417 case cscSwitchMode:
418 D(bug("cscSwitchMode (Display Manager support) \nMode:%02x ID:%04x Page:%d\n",
419 ReadMacInt16(param + csMode), ReadMacInt32(param + csData), ReadMacInt16(param + csPage)));
420 return video_mode_change(csSave, param);
421
422 case cscSavePreferredConfiguration:
423 D(bug("SavePreferredConfiguration\n"));
424 save_conf_id = ReadMacInt32(param + csData);
425 save_conf_mode = ReadMacInt16(param + csMode);
426 return noErr;
427
428 case cscSetHardwareCursor: {
429 // D(bug("SetHardwareCursor\n"));
430 csSave->cursorSet = false;
431 bool changed = false;
432
433 // Get cursor data even on a screen, to set the right cursor image when switching back to a window
434 // Image
435 uint32 cursor = ReadMacInt32(param); // Pointer to CursorImage
436 uint32 pmhandle = ReadMacInt32(cursor + ciCursorPixMap);
437 if (pmhandle == 0 || ReadMacInt32(pmhandle) == 0)
438 return controlErr;
439 uint32 pixmap = ReadMacInt32(pmhandle);
440 if (memcmp(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32)) {
441 memcpy(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32);
442 changed = true;
443 }
444
445 // Mask
446 uint32 bmhandle = ReadMacInt32(cursor + ciCursorBitMask);
447 if (bmhandle == 0 || ReadMacInt32(bmhandle) == 0)
448 return controlErr;
449 uint32 bitmap = ReadMacInt32(bmhandle);
450 if (memcmp(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32)) {
451 memcpy(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32);
452 changed = true;
453 }
454
455 // Hotspot (!! this doesn't work)
456 MacCursor[2] = ReadMacInt8(0x885);
457 MacCursor[3] = ReadMacInt8(0x887);
458
459 // Set new cursor image
460 if (display_type == DIS_SCREEN)
461 return controlErr;
462 if (changed)
463 video_set_cursor();
464
465 csSave->cursorSet = true;
466 return noErr;
467 }
468
469 case cscDrawHardwareCursor:
470 // D(bug("DrawHardwareCursor\n"));
471 csSave->cursorX = ReadMacInt32(param + csCursorX);
472 csSave->cursorY = ReadMacInt32(param + csCursorY);
473 csSave->cursorVisible = ReadMacInt32(param + csCursorVisible);
474 return noErr;
475
476 case 43: { // Driver Gestalt
477 uint32 sel = ReadMacInt32(pb + csParam);
478 D(bug(" driver gestalt %c%c%c%c\n", sel >> 24, sel >> 16, sel >> 8, sel));
479 switch (sel) {
480 case FOURCC('v','e','r','s'):
481 WriteMacInt32(pb + csParam + 4, 0x01008000);
482 break;
483 case FOURCC('i','n','t','f'):
484 WriteMacInt32(pb + csParam + 4, FOURCC('c','a','r','d'));
485 break;
486 case FOURCC('s','y','n','c'):
487 WriteMacInt32(pb + csParam + 4, 0x01000000);
488 break;
489 default:
490 return statusErr;
491 };
492 return noErr;
493 }
494
495 default:
496 D(bug(" unknown control code %d\n", code));
497 return controlErr;
498 }
499 }
500
501
502 /*
503 * Video driver status routine
504 */
505
506 // Search for given AppleID in mode table
507 static bool has_mode(uint32 id)
508 {
509 VideoInfo *p = VModes;
510 while (p->viType != DIS_INVALID) {
511 if (p->viAppleID == id)
512 return true;
513 p++;
514 }
515 return false;
516 }
517
518 // Find maximum depth for given AppleID
519 static uint32 max_depth(uint32 id)
520 {
521 uint32 max = APPLE_1_BIT;
522 VideoInfo *p = VModes;
523 while (p->viType != DIS_INVALID) {
524 if (p->viAppleID == id && p->viAppleMode > max)
525 max = p->viAppleMode;
526 p++;
527 }
528 return max;
529 }
530
531 static int16 VideoStatus(uint32 pb, VidLocals *csSave)
532 {
533 int16 code = ReadMacInt16(pb + csCode);
534 D(bug("VideoStatus %d: ", code));
535 uint32 param = ReadMacInt32(pb + csParam);
536 switch (code) {
537
538 case cscGetMode: // GetMode
539 D(bug("GetMode\n"));
540 WriteMacInt32(param + csBaseAddr, csSave->saveBaseAddr);
541 WriteMacInt16(param + csMode, csSave->saveMode);
542 WriteMacInt16(param + csPage, csSave->savePage);
543 D(bug("return: mode:%04x page:%04x ", ReadMacInt16(param + csMode),
544 ReadMacInt16(param + csPage)));
545 D(bug("base adress %08lx\n", ReadMacInt32(param + csBaseAddr)));
546 return noErr;
547
548 case cscGetEntries: { // GetEntries
549 D(bug("GetEntries\n"));
550 ColorSpec *d_pal = (ColorSpec *)Mac2HostAddr(ReadMacInt32(param + csTable));
551 int16 start = ReadMacInt16(param + csStart);
552 int16 count = ReadMacInt16(param + csCount);
553 rgb_color *s_pal;
554 if ((VModes[cur_mode].viAppleMode == APPLE_32_BIT)||
555 (VModes[cur_mode].viAppleMode == APPLE_16_BIT)) {
556 D(bug("ERROR: GetEntries in direct mode \n"));
557 return statusErr;
558 }
559 if (start >= 0) { // indexed get
560 s_pal = &(mac_pal[start]);
561 for (uint16 i=0;i<count;i++) {
562 (*d_pal).red=(uint16)((*s_pal).red)*0x101;
563 (*d_pal).green=(uint16)((*s_pal).green)*0x101;
564 (*d_pal).blue=(uint16)((*s_pal).blue)*0x101;
565 d_pal++; s_pal++;
566 }
567 } else { // selected set
568 for (uint16 i=0;i<count;i++) {
569 s_pal = &(mac_pal[(*d_pal).value]);
570 (*d_pal).red=(uint16)((*s_pal).red)*0x101;
571 (*d_pal).green=(uint16)((*s_pal).green)*0x101;
572 (*d_pal).blue=(uint16)((*s_pal).blue)*0x101;
573 d_pal++;
574 }
575 };
576 return noErr;
577 }
578
579 case cscGetPageCnt: // GetPage
580 D(bug("GetPage\n"));
581 WriteMacInt16(param + csPage, 1);
582 return noErr;
583
584 case cscGetPageBase: // GetPageBase
585 D(bug("GetPageBase\n"));
586 WriteMacInt32(param + csBaseAddr, csSave->saveBaseAddr);
587 return noErr;
588
589 case cscGetGray: // GetGray
590 D(bug("GetGray\n"));
591 WriteMacInt8(param, csSave->luminanceMapping ? 1 : 0);
592 return noErr;
593
594 case cscGetInterrupt: // GetInterrupt
595 D(bug("GetInterrupt\n"));
596 WriteMacInt8(param, csSave->interruptsEnabled ? 0 : 1);
597 return noErr;
598
599 case cscGetGamma: // GetGamma
600 D(bug("GetGamma\n"));
601 WriteMacInt32(param, (uint32)csSave->gammaTable);
602 return statusErr;
603
604 case cscGetDefaultMode: // GetDefaultMode
605 D(bug("GetDefaultMode\n"));
606 return statusErr;
607
608 case cscGetCurMode: // GetCurMode
609 D(bug("GetCurMode\n"));
610 WriteMacInt16(param + csMode, csSave->saveMode);
611 WriteMacInt32(param + csData, csSave->saveData);
612 WriteMacInt16(param + csPage, csSave->savePage);
613 WriteMacInt32(param + csBaseAddr, csSave->saveBaseAddr);
614
615 D(bug("return: mode:%04x ID:%08lx page:%04x ", ReadMacInt16(param + csMode),
616 ReadMacInt32(param + csData), ReadMacInt16(param + csPage)));
617 D(bug("base adress %08lx\n", ReadMacInt32(param + csBaseAddr)));
618 return noErr;
619
620 case cscGetConnection: // GetConnection
621 D(bug("GetConnection\n"));
622 WriteMacInt16(param + csDisplayType, kMultiModeCRT3Connect);
623 WriteMacInt8(param + csConnectTaggedType, 6);
624 WriteMacInt8(param + csConnectTaggedData, 0x23);
625 WriteMacInt32(param + csConnectFlags, (1<<kAllModesValid)|(1<<kAllModesSafe));
626 WriteMacInt32(param + csDisplayComponent, 0);
627 return noErr;
628
629 case cscGetModeBaseAddress:
630 D(bug("GetModeBaseAddress (obsolete !) \n"));
631 return statusErr;
632
633 case cscGetPreferredConfiguration:
634 D(bug("GetPreferredConfiguration \n"));
635 WriteMacInt16(param + csMode, save_conf_mode);
636 WriteMacInt32(param + csData, save_conf_id);
637 return noErr;
638
639 case cscGetNextResolution: {
640 D(bug("GetNextResolution \n"));
641 int work_id = ReadMacInt32(param + csPreviousDisplayModeID);
642 switch (work_id) {
643 case kDisplayModeIDCurrent:
644 work_id = csSave->saveData;
645 break;
646 case kDisplayModeIDFindFirstResolution:
647 work_id = APPLE_ID_MIN;
648 while (!has_mode(work_id))
649 work_id ++;
650 break;
651 default:
652 if (!has_mode(work_id))
653 return paramErr;
654 work_id++;
655 while (!has_mode(work_id)) {
656 work_id++;
657 if (work_id > APPLE_ID_MAX) {
658 WriteMacInt32(param + csRIDisplayModeID, kDisplayModeIDNoMoreResolutions);
659 return noErr;
660 }
661 }
662 break;
663 }
664 WriteMacInt32(param + csRIDisplayModeID, work_id);
665 WriteMacInt16(param + csMaxDepthMode, max_depth(work_id));
666 switch (work_id) {
667 case APPLE_640x480:
668 WriteMacInt32(param + csHorizontalPixels, 640);
669 WriteMacInt32(param + csVerticalLines, 480);
670 WriteMacInt32(param + csRefreshRate, 75<<16);
671 break;
672 case APPLE_W_640x480:
673 WriteMacInt32(param + csHorizontalPixels, 640);
674 WriteMacInt32(param + csVerticalLines, 480);
675 WriteMacInt32(param + csRefreshRate, 60<<16);
676 break;
677 case APPLE_800x600:
678 WriteMacInt32(param + csHorizontalPixels, 800);
679 WriteMacInt32(param + csVerticalLines, 600);
680 WriteMacInt32(param + csRefreshRate, 75<<16);
681 break;
682 case APPLE_W_800x600:
683 WriteMacInt32(param + csHorizontalPixels, 800);
684 WriteMacInt32(param + csVerticalLines, 600);
685 WriteMacInt32(param + csRefreshRate, 60<<16);
686 break;
687 case APPLE_1024x768:
688 WriteMacInt32(param + csHorizontalPixels, 1024);
689 WriteMacInt32(param + csVerticalLines, 768);
690 WriteMacInt32(param + csRefreshRate, 75<<16);
691 break;
692 case APPLE_1152x900:
693 WriteMacInt32(param + csHorizontalPixels, 1152);
694 WriteMacInt32(param + csVerticalLines, 900);
695 WriteMacInt32(param + csRefreshRate, 75<<16);
696 break;
697 case APPLE_1280x1024:
698 WriteMacInt32(param + csHorizontalPixels, 1280);
699 WriteMacInt32(param + csVerticalLines, 1024);
700 WriteMacInt32(param + csRefreshRate, 75<<16);
701 break;
702 case APPLE_1600x1200:
703 WriteMacInt32(param + csHorizontalPixels, 1600);
704 WriteMacInt32(param + csVerticalLines, 1200);
705 WriteMacInt32(param + csRefreshRate, 75<<16);
706 break;
707 }
708 return noErr;
709 }
710
711 case cscGetVideoParameters: // GetVideoParameters
712 D(bug("GetVideoParameters ID:%08lx Depth:%04x\n",
713 ReadMacInt32(param + csDisplayModeID),
714 ReadMacInt16(param + csDepthMode)));
715
716 // find right video mode
717 for (int i=0; VModes[i].viType!=DIS_INVALID; i++) {
718 if ((ReadMacInt16(param + csDepthMode) == VModes[i].viAppleMode) &&
719 (ReadMacInt32(param + csDisplayModeID) == VModes[i].viAppleID)) {
720 uint32 vpb = ReadMacInt32(param + csVPBlockPtr);
721 WriteMacInt32(vpb + vpBaseOffset, 0);
722 WriteMacInt16(vpb + vpRowBytes, VModes[i].viRowBytes);
723 WriteMacInt16(vpb + vpBounds, 0);
724 WriteMacInt16(vpb + vpBounds + 2, 0);
725 WriteMacInt16(vpb + vpBounds + 4, VModes[i].viYsize);
726 WriteMacInt16(vpb + vpBounds + 6, VModes[i].viXsize);
727 WriteMacInt16(vpb + vpVersion, 0); // Pixel Map version number
728 WriteMacInt16(vpb + vpPackType, 0);
729 WriteMacInt32(vpb + vpPackSize, 0);
730 WriteMacInt32(vpb + vpHRes, 0x00480000); // horiz res of the device (ppi)
731 WriteMacInt32(vpb + vpVRes, 0x00480000); // vert res of the device (ppi)
732 switch (VModes[i].viAppleMode) {
733 case APPLE_1_BIT:
734 WriteMacInt16(vpb + vpPixelType, 0);
735 WriteMacInt16(vpb + vpPixelSize, 1);
736 WriteMacInt16(vpb + vpCmpCount, 1);
737 WriteMacInt16(vpb + vpCmpSize, 1);
738 WriteMacInt32(param + csDeviceType, 0); // CLUT
739 break;
740 case APPLE_2_BIT:
741 WriteMacInt16(vpb + vpPixelType, 0);
742 WriteMacInt16(vpb + vpPixelSize, 2);
743 WriteMacInt16(vpb + vpCmpCount, 1);
744 WriteMacInt16(vpb + vpCmpSize, 2);
745 WriteMacInt32(param + csDeviceType, 0); // CLUT
746 break;
747 case APPLE_4_BIT:
748 WriteMacInt16(vpb + vpPixelType, 0);
749 WriteMacInt16(vpb + vpPixelSize, 4);
750 WriteMacInt16(vpb + vpCmpCount, 1);
751 WriteMacInt16(vpb + vpCmpSize, 4);
752 WriteMacInt32(param + csDeviceType, 0); // CLUT
753 break;
754 case APPLE_8_BIT:
755 WriteMacInt16(vpb + vpPixelType, 0);
756 WriteMacInt16(vpb + vpPixelSize, 8);
757 WriteMacInt16(vpb + vpCmpCount, 1);
758 WriteMacInt16(vpb + vpCmpSize, 8);
759 WriteMacInt32(param + csDeviceType, 0); // CLUT
760 break;
761 case APPLE_16_BIT:
762 WriteMacInt16(vpb + vpPixelType, 0x10);
763 WriteMacInt16(vpb + vpPixelSize, 16);
764 WriteMacInt16(vpb + vpCmpCount, 3);
765 WriteMacInt16(vpb + vpCmpSize, 5);
766 WriteMacInt32(param + csDeviceType, 2); // DIRECT
767 break;
768 case APPLE_32_BIT:
769 WriteMacInt16(vpb + vpPixelType, 0x10);
770 WriteMacInt16(vpb + vpPixelSize, 32);
771 WriteMacInt16(vpb + vpCmpCount, 3);
772 WriteMacInt16(vpb + vpCmpSize, 8);
773 WriteMacInt32(param + csDeviceType, 2); // DIRECT
774 break;
775 }
776 WriteMacInt32(param + csPageCount, 1);
777 return noErr;
778 }
779 }
780 return paramErr;
781
782 case cscGetModeTiming:
783 D(bug("GetModeTiming mode %08lx\n", ReadMacInt32(param + csTimingMode)));
784 WriteMacInt32(param + csTimingFormat, kDeclROMtables);
785 WriteMacInt32(param + csTimingFlags, (1<<kModeValid)|(1<<kModeSafe)|(1<<kShowModeNow)); // Mode valid, safe, default and shown in Monitors panel
786 for (int i=0; VModes[i].viType!=DIS_INVALID; i++) {
787 if (ReadMacInt32(param + csTimingMode) == VModes[i].viAppleID) {
788 uint32 timing = timingUnknown;
789 uint32 flags = (1<<kModeValid) | (1<<kShowModeNow);
790 switch (VModes[i].viAppleID) {
791 case APPLE_640x480:
792 timing = timingVESA_640x480_75hz;
793 flags |= (1<<kModeSafe);
794 break;
795 case APPLE_W_640x480:
796 timing = timingVESA_640x480_60hz;
797 flags |= (1<<kModeSafe);
798 break;
799 case APPLE_800x600:
800 timing = timingVESA_800x600_75hz;
801 flags |= (1<<kModeSafe);
802 break;
803 case APPLE_W_800x600:
804 timing = timingVESA_800x600_60hz;
805 flags |= (1<<kModeSafe);
806 break;
807 case APPLE_1024x768:
808 timing = timingVESA_1024x768_75hz;
809 break;
810 case APPLE_1152x900:
811 timing = timingApple_1152x870_75hz;
812 break;
813 case APPLE_1280x1024:
814 timing = timingVESA_1280x960_75hz;
815 break;
816 case APPLE_1600x1200:
817 timing = timingVESA_1600x1200_75hz;
818 break;
819 default:
820 timing = timingUnknown;
821 break;
822 }
823 WriteMacInt32(param + csTimingData, timing);
824 WriteMacInt32(param + csTimingFlags, flags);
825 return noErr;
826 }
827 }
828 return paramErr;
829
830 case cscSupportsHardwareCursor:
831 D(bug("SupportsHardwareCursor\n"));
832 WriteMacInt32(param, 1);
833 return noErr;
834
835 case cscGetHardwareCursorDrawState:
836 D(bug("GetHardwareCursorDrawState\n"));
837 WriteMacInt32(param + csCursorX, csSave->cursorX);
838 WriteMacInt32(param + csCursorY, csSave->cursorY);
839 WriteMacInt32(param + csCursorVisible, csSave->cursorVisible);
840 WriteMacInt32(param + csCursorSet, csSave->cursorSet);
841 return noErr;
842
843 default:
844 D(bug(" unknown status code %d\n", code));
845 return statusErr;
846 }
847 }
848
849
850 /*
851 * Video driver close routine
852 */
853
854 static int16 VideoClose(uint32 pb, VidLocals *csSave)
855 {
856 D(bug("VideoClose\n"));
857
858 // Delete interrupt service
859 csSave->interruptsEnabled = false;
860 VSLDisposeInterruptService(csSave->vslServiceID);
861
862 return noErr;
863 }
864
865
866 /*
867 * Native (PCI) driver entry
868 */
869
870 int16 VideoDoDriverIO(void *spaceID, void *commandID, void *commandContents, uint32 commandCode, uint32 commandKind)
871 {
872 // D(bug("VideoDoDriverIO space %p, command %p, contents %p, code %d, kind %d\n", spaceID, commandID, commandContents, commandCode, commandKind));
873 int16 err = noErr;
874
875 switch (commandCode) {
876 case kInitializeCommand:
877 case kReplaceCommand:
878 if (private_data != NULL) // Might be left over from a reboot
879 delete private_data->gammaTable;
880 delete private_data;
881
882 iocic_tvect = (uint32)FindLibSymbol("\021DriverServicesLib", "\023IOCommandIsComplete");
883 D(bug("IOCommandIsComplete TVECT at %08lx\n", iocic_tvect));
884 if (iocic_tvect == 0) {
885 printf("FATAL: VideoDoDriverIO(): Can't find IOCommandIsComplete()\n");
886 err = -1;
887 break;
888 }
889 vslnewis_tvect = (uint32)FindLibSymbol("\020VideoServicesLib", "\026VSLNewInterruptService");
890 D(bug("VSLNewInterruptService TVECT at %08lx\n", vslnewis_tvect));
891 if (vslnewis_tvect == 0) {
892 printf("FATAL: VideoDoDriverIO(): Can't find VSLNewInterruptService()\n");
893 err = -1;
894 break;
895 }
896 vsldisposeis_tvect = (uint32)FindLibSymbol("\020VideoServicesLib", "\032VSLDisposeInterruptService");
897 D(bug("VSLDisposeInterruptService TVECT at %08lx\n", vsldisposeis_tvect));
898 if (vsldisposeis_tvect == 0) {
899 printf("FATAL: VideoDoDriverIO(): Can't find VSLDisposeInterruptService()\n");
900 err = -1;
901 break;
902 }
903 vsldois_tvect = (uint32)FindLibSymbol("\020VideoServicesLib", "\025VSLDoInterruptService");
904 D(bug("VSLDoInterruptService TVECT at %08lx\n", vsldois_tvect));
905 if (vsldois_tvect == 0) {
906 printf("FATAL: VideoDoDriverIO(): Can't find VSLDoInterruptService()\n");
907 err = -1;
908 break;
909 }
910 nqdmisc_tvect = (uint32)FindLibSymbol("\014InterfaceLib", "\007NQDMisc");
911 D(bug("NQDMisc TVECT at %08lx\n", nqdmisc_tvect));
912 if (nqdmisc_tvect == 0) {
913 printf("FATAL: VideoDoDriverIO(): Can't find NQDMisc()\n");
914 err = -1;
915 break;
916 }
917
918 private_data = new VidLocals;
919 private_data->gammaTable = NULL;
920 memcpy(private_data->regEntryID, (uint8 *)commandContents + 2, 16); // DriverInitInfo.deviceEntry
921 private_data->interruptsEnabled = false; // Disable interrupts
922 break;
923
924 case kFinalizeCommand:
925 case kSupersededCommand:
926 if (private_data != NULL)
927 delete private_data->gammaTable;
928 delete private_data;
929 private_data = NULL;
930 break;
931
932 case kOpenCommand:
933 err = VideoOpen((uint32)commandContents, private_data);
934 break;
935
936 case kCloseCommand:
937 err = VideoClose((uint32)commandContents, private_data);
938 break;
939
940 case kControlCommand:
941 err = VideoControl((uint32)commandContents, private_data);
942 break;
943
944 case kStatusCommand:
945 err = VideoStatus((uint32)commandContents, private_data);
946 break;
947
948 case kReadCommand:
949 case kWriteCommand:
950 break;
951
952 case kKillIOCommand:
953 err = abortErr;
954 break;
955
956 default:
957 err = paramErr;
958 break;
959 }
960
961 if (commandKind == kImmediateIOCommandKind)
962 return err;
963 else
964 return IOCommandIsComplete(commandID, err);
965 }