ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/video.cpp
Revision: 1.6
Committed: 2004-04-10T23:15:20Z (20 years, 1 month ago) by gbeauche
Branch: MAIN
Changes since 1.5: +65 -64 lines
Log Message:
Merge run-time depth switching code from Basilisk II.

File Contents

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