ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/video.cpp
Revision: 1.2
Committed: 2003-09-29T20:30:19Z (21 years, 1 month ago) by gbeauche
Branch: MAIN
Changes since 1.1: +3 -2 lines
Log Message:
first round of little endian fixes

File Contents

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