ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/video.cpp
Revision: 1.14
Committed: 2005-03-27T13:44:45Z (19 years, 1 month ago) by gbeauche
Branch: MAIN
Changes since 1.13: +23 -0 lines
Log Message:
Add custom video modes for full screen in unsual resolutions (e.g. 1400x1050).
X11 and SDL infrastructures have yet to be implemented

File Contents

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