ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/video.cpp
Revision: 1.7
Committed: 2004-04-13T22:22:20Z (20 years, 1 month ago) by gbeauche
Branch: MAIN
Changes since 1.6: +8 -0 lines
Log Message:
Fix DGA mode for emulated PPC targets. It currently doesn't work in native
mode as the stack is corrupted and we are jumping to garbage when moving
the mouse. Also add 1152x768 resolution from PBG4, but make timing match
the 1152x870 version.

Cleanups, further merges from Basilisk II tree.

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 gbeauche 1.7 case APPLE_1152x768:
694     WriteMacInt32(param + csHorizontalPixels, 1152);
695     WriteMacInt32(param + csVerticalLines, 768);
696     WriteMacInt32(param + csRefreshRate, 75<<16);
697     break;
698 cebix 1.1 case APPLE_1152x900:
699     WriteMacInt32(param + csHorizontalPixels, 1152);
700     WriteMacInt32(param + csVerticalLines, 900);
701     WriteMacInt32(param + csRefreshRate, 75<<16);
702     break;
703     case APPLE_1280x1024:
704     WriteMacInt32(param + csHorizontalPixels, 1280);
705     WriteMacInt32(param + csVerticalLines, 1024);
706     WriteMacInt32(param + csRefreshRate, 75<<16);
707     break;
708     case APPLE_1600x1200:
709     WriteMacInt32(param + csHorizontalPixels, 1600);
710     WriteMacInt32(param + csVerticalLines, 1200);
711     WriteMacInt32(param + csRefreshRate, 75<<16);
712     break;
713     }
714     return noErr;
715     }
716    
717     case cscGetVideoParameters: // GetVideoParameters
718     D(bug("GetVideoParameters ID:%08lx Depth:%04x\n",
719     ReadMacInt32(param + csDisplayModeID),
720     ReadMacInt16(param + csDepthMode)));
721    
722     // find right video mode
723     for (int i=0; VModes[i].viType!=DIS_INVALID; i++) {
724     if ((ReadMacInt16(param + csDepthMode) == VModes[i].viAppleMode) &&
725     (ReadMacInt32(param + csDisplayModeID) == VModes[i].viAppleID)) {
726     uint32 vpb = ReadMacInt32(param + csVPBlockPtr);
727     WriteMacInt32(vpb + vpBaseOffset, 0);
728     WriteMacInt16(vpb + vpRowBytes, VModes[i].viRowBytes);
729     WriteMacInt16(vpb + vpBounds, 0);
730     WriteMacInt16(vpb + vpBounds + 2, 0);
731     WriteMacInt16(vpb + vpBounds + 4, VModes[i].viYsize);
732     WriteMacInt16(vpb + vpBounds + 6, VModes[i].viXsize);
733     WriteMacInt16(vpb + vpVersion, 0); // Pixel Map version number
734     WriteMacInt16(vpb + vpPackType, 0);
735     WriteMacInt32(vpb + vpPackSize, 0);
736     WriteMacInt32(vpb + vpHRes, 0x00480000); // horiz res of the device (ppi)
737     WriteMacInt32(vpb + vpVRes, 0x00480000); // vert res of the device (ppi)
738     switch (VModes[i].viAppleMode) {
739     case APPLE_1_BIT:
740     WriteMacInt16(vpb + vpPixelType, 0);
741     WriteMacInt16(vpb + vpPixelSize, 1);
742     WriteMacInt16(vpb + vpCmpCount, 1);
743     WriteMacInt16(vpb + vpCmpSize, 1);
744     WriteMacInt32(param + csDeviceType, 0); // CLUT
745     break;
746     case APPLE_2_BIT:
747     WriteMacInt16(vpb + vpPixelType, 0);
748     WriteMacInt16(vpb + vpPixelSize, 2);
749     WriteMacInt16(vpb + vpCmpCount, 1);
750     WriteMacInt16(vpb + vpCmpSize, 2);
751     WriteMacInt32(param + csDeviceType, 0); // CLUT
752     break;
753     case APPLE_4_BIT:
754     WriteMacInt16(vpb + vpPixelType, 0);
755     WriteMacInt16(vpb + vpPixelSize, 4);
756     WriteMacInt16(vpb + vpCmpCount, 1);
757     WriteMacInt16(vpb + vpCmpSize, 4);
758     WriteMacInt32(param + csDeviceType, 0); // CLUT
759     break;
760     case APPLE_8_BIT:
761     WriteMacInt16(vpb + vpPixelType, 0);
762     WriteMacInt16(vpb + vpPixelSize, 8);
763     WriteMacInt16(vpb + vpCmpCount, 1);
764     WriteMacInt16(vpb + vpCmpSize, 8);
765     WriteMacInt32(param + csDeviceType, 0); // CLUT
766     break;
767     case APPLE_16_BIT:
768     WriteMacInt16(vpb + vpPixelType, 0x10);
769     WriteMacInt16(vpb + vpPixelSize, 16);
770     WriteMacInt16(vpb + vpCmpCount, 3);
771     WriteMacInt16(vpb + vpCmpSize, 5);
772     WriteMacInt32(param + csDeviceType, 2); // DIRECT
773     break;
774     case APPLE_32_BIT:
775     WriteMacInt16(vpb + vpPixelType, 0x10);
776     WriteMacInt16(vpb + vpPixelSize, 32);
777     WriteMacInt16(vpb + vpCmpCount, 3);
778     WriteMacInt16(vpb + vpCmpSize, 8);
779     WriteMacInt32(param + csDeviceType, 2); // DIRECT
780     break;
781     }
782     WriteMacInt32(param + csPageCount, 1);
783     return noErr;
784     }
785     }
786     return paramErr;
787    
788     case cscGetModeTiming:
789     D(bug("GetModeTiming mode %08lx\n", ReadMacInt32(param + csTimingMode)));
790     WriteMacInt32(param + csTimingFormat, kDeclROMtables);
791     WriteMacInt32(param + csTimingFlags, (1<<kModeValid)|(1<<kModeSafe)|(1<<kShowModeNow)); // Mode valid, safe, default and shown in Monitors panel
792     for (int i=0; VModes[i].viType!=DIS_INVALID; i++) {
793     if (ReadMacInt32(param + csTimingMode) == VModes[i].viAppleID) {
794     uint32 timing = timingUnknown;
795     uint32 flags = (1<<kModeValid) | (1<<kShowModeNow);
796     switch (VModes[i].viAppleID) {
797     case APPLE_640x480:
798     timing = timingVESA_640x480_75hz;
799     flags |= (1<<kModeSafe);
800     break;
801     case APPLE_W_640x480:
802     timing = timingVESA_640x480_60hz;
803     flags |= (1<<kModeSafe);
804     break;
805     case APPLE_800x600:
806     timing = timingVESA_800x600_75hz;
807     flags |= (1<<kModeSafe);
808     break;
809     case APPLE_W_800x600:
810     timing = timingVESA_800x600_60hz;
811     flags |= (1<<kModeSafe);
812     break;
813     case APPLE_1024x768:
814     timing = timingVESA_1024x768_75hz;
815 gbeauche 1.7 break;
816     case APPLE_1152x768:
817     timing = timingApple_1152x870_75hz; // FIXME
818 cebix 1.1 break;
819     case APPLE_1152x900:
820     timing = timingApple_1152x870_75hz;
821     break;
822     case APPLE_1280x1024:
823     timing = timingVESA_1280x960_75hz;
824     break;
825     case APPLE_1600x1200:
826     timing = timingVESA_1600x1200_75hz;
827     break;
828     default:
829     timing = timingUnknown;
830     break;
831     }
832     WriteMacInt32(param + csTimingData, timing);
833     WriteMacInt32(param + csTimingFlags, flags);
834     return noErr;
835     }
836     }
837     return paramErr;
838    
839     case cscSupportsHardwareCursor:
840     D(bug("SupportsHardwareCursor\n"));
841     WriteMacInt32(param, 1);
842     return noErr;
843    
844     case cscGetHardwareCursorDrawState:
845     D(bug("GetHardwareCursorDrawState\n"));
846     WriteMacInt32(param + csCursorX, csSave->cursorX);
847     WriteMacInt32(param + csCursorY, csSave->cursorY);
848     WriteMacInt32(param + csCursorVisible, csSave->cursorVisible);
849     WriteMacInt32(param + csCursorSet, csSave->cursorSet);
850     return noErr;
851    
852     default:
853     D(bug(" unknown status code %d\n", code));
854     return statusErr;
855     }
856     }
857    
858    
859     /*
860     * Video driver close routine
861     */
862    
863     static int16 VideoClose(uint32 pb, VidLocals *csSave)
864     {
865     D(bug("VideoClose\n"));
866    
867     // Delete interrupt service
868     csSave->interruptsEnabled = false;
869     VSLDisposeInterruptService(csSave->vslServiceID);
870    
871     return noErr;
872     }
873    
874    
875     /*
876     * Native (PCI) driver entry
877     */
878    
879     int16 VideoDoDriverIO(void *spaceID, void *commandID, void *commandContents, uint32 commandCode, uint32 commandKind)
880     {
881     // D(bug("VideoDoDriverIO space %p, command %p, contents %p, code %d, kind %d\n", spaceID, commandID, commandContents, commandCode, commandKind));
882     int16 err = noErr;
883    
884     switch (commandCode) {
885     case kInitializeCommand:
886     case kReplaceCommand:
887     if (private_data != NULL) // Might be left over from a reboot
888     delete private_data->gammaTable;
889     delete private_data;
890    
891     iocic_tvect = (uint32)FindLibSymbol("\021DriverServicesLib", "\023IOCommandIsComplete");
892     D(bug("IOCommandIsComplete TVECT at %08lx\n", iocic_tvect));
893     if (iocic_tvect == 0) {
894     printf("FATAL: VideoDoDriverIO(): Can't find IOCommandIsComplete()\n");
895     err = -1;
896     break;
897     }
898     vslnewis_tvect = (uint32)FindLibSymbol("\020VideoServicesLib", "\026VSLNewInterruptService");
899     D(bug("VSLNewInterruptService TVECT at %08lx\n", vslnewis_tvect));
900     if (vslnewis_tvect == 0) {
901     printf("FATAL: VideoDoDriverIO(): Can't find VSLNewInterruptService()\n");
902     err = -1;
903     break;
904     }
905     vsldisposeis_tvect = (uint32)FindLibSymbol("\020VideoServicesLib", "\032VSLDisposeInterruptService");
906     D(bug("VSLDisposeInterruptService TVECT at %08lx\n", vsldisposeis_tvect));
907     if (vsldisposeis_tvect == 0) {
908     printf("FATAL: VideoDoDriverIO(): Can't find VSLDisposeInterruptService()\n");
909     err = -1;
910     break;
911     }
912     vsldois_tvect = (uint32)FindLibSymbol("\020VideoServicesLib", "\025VSLDoInterruptService");
913     D(bug("VSLDoInterruptService TVECT at %08lx\n", vsldois_tvect));
914     if (vsldois_tvect == 0) {
915     printf("FATAL: VideoDoDriverIO(): Can't find VSLDoInterruptService()\n");
916     err = -1;
917     break;
918     }
919     nqdmisc_tvect = (uint32)FindLibSymbol("\014InterfaceLib", "\007NQDMisc");
920     D(bug("NQDMisc TVECT at %08lx\n", nqdmisc_tvect));
921     if (nqdmisc_tvect == 0) {
922     printf("FATAL: VideoDoDriverIO(): Can't find NQDMisc()\n");
923     err = -1;
924     break;
925     }
926    
927     private_data = new VidLocals;
928     private_data->gammaTable = NULL;
929     memcpy(private_data->regEntryID, (uint8 *)commandContents + 2, 16); // DriverInitInfo.deviceEntry
930     private_data->interruptsEnabled = false; // Disable interrupts
931     break;
932    
933     case kFinalizeCommand:
934     case kSupersededCommand:
935     if (private_data != NULL)
936     delete private_data->gammaTable;
937     delete private_data;
938     private_data = NULL;
939     break;
940    
941     case kOpenCommand:
942     err = VideoOpen((uint32)commandContents, private_data);
943     break;
944    
945     case kCloseCommand:
946     err = VideoClose((uint32)commandContents, private_data);
947     break;
948    
949     case kControlCommand:
950     err = VideoControl((uint32)commandContents, private_data);
951     break;
952    
953     case kStatusCommand:
954     err = VideoStatus((uint32)commandContents, private_data);
955     break;
956    
957     case kReadCommand:
958     case kWriteCommand:
959     break;
960    
961     case kKillIOCommand:
962     err = abortErr;
963     break;
964    
965     default:
966     err = paramErr;
967     break;
968     }
969    
970     if (commandKind == kImmediateIOCommandKind)
971     return err;
972     else
973     return IOCommandIsComplete(commandID, err);
974     }