ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/video.cpp
Revision: 1.13
Committed: 2005-01-30T21:48:19Z (19 years, 9 months ago) by gbeauche
Branch: MAIN
Changes since 1.12: +1 -1 lines
Log Message:
Happy New Year 2005!

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * video.cpp - Video/graphics emulation
3     *
4 gbeauche 1.13 * SheepShaver (C) 1997-2005 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 gbeauche 1.9 static inline int16 IOCommandIsComplete(uintptr arg1, int16 arg2)
78 cebix 1.1 {
79 gbeauche 1.9 return (int16)CallMacOS2(iocic_ptr, iocic_tvect, (void *)arg1, arg2);
80 cebix 1.1 }
81     typedef int16 (*vslnewis_ptr)(void *, uint32, uint32 *);
82     static uint32 vslnewis_tvect = 0;
83 gbeauche 1.9 static inline int16 VSLNewInterruptService(uintptr arg1, uint32 arg2, uintptr arg3)
84 cebix 1.1 {
85 gbeauche 1.9 return (int16)CallMacOS3(vslnewis_ptr, vslnewis_tvect, (void *)arg1, arg2, (uint32 *)arg3);
86 cebix 1.1 }
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 gbeauche 1.9 void NQDMisc(uint32 arg1, uintptr arg2)
102 cebix 1.1 {
103 gbeauche 1.9 CallMacOS2(nqdmisc_ptr, nqdmisc_tvect, arg1, (void *)arg2);
104 cebix 1.1 }
105    
106    
107     // Prototypes
108     static int16 set_gamma(VidLocals *csSave, uint32 gamma);
109    
110    
111     /*
112     * Tell whether window/screen is activated or not (for mouse/keyboard polling)
113     */
114    
115     bool VideoActivated(void)
116     {
117     return video_activated;
118     }
119    
120    
121     /*
122     * Create RGB snapshot of current screen
123     */
124    
125     bool VideoSnapshot(int xsize, int ysize, uint8 *p)
126     {
127     if (display_type == DIS_WINDOW) {
128     uint8 *screen = (uint8 *)private_data->saveBaseAddr;
129     uint32 row_bytes = VModes[cur_mode].viRowBytes;
130     uint32 y2size = VModes[cur_mode].viYsize;
131     uint32 x2size = VModes[cur_mode].viXsize;
132     for (int j=0;j<ysize;j++) {
133     for (int i=0;i<xsize;i++) {
134     *p++ = mac_pal[screen[uint32(float(j)*float(y2size)/float(ysize))*row_bytes+uint32(float(i)*float(x2size)/float(xsize))]].red;
135     *p++ = mac_pal[screen[uint32(float(j)*float(y2size)/float(ysize))*row_bytes+uint32(float(i)*float(x2size)/float(xsize))]].green;
136     *p++ = mac_pal[screen[uint32(float(j)*float(y2size)/float(ysize))*row_bytes+uint32(float(i)*float(x2size)/float(xsize))]].blue;
137     }
138     }
139     return true;
140     }
141     return false;
142     }
143    
144    
145     /*
146     * Video driver open routine
147     */
148    
149     static int16 VideoOpen(uint32 pb, VidLocals *csSave)
150     {
151     D(bug("Video Open\n"));
152    
153     // Set up VidLocals
154     csSave->saveBaseAddr = screen_base;
155     csSave->saveData = VModes[cur_mode].viAppleID;// First mode ...
156     csSave->saveMode = VModes[cur_mode].viAppleMode;
157     csSave->savePage = 0;
158     csSave->saveVidParms = 0; // Add the right table
159     csSave->luminanceMapping = false;
160     csSave->cursorX = 0;
161     csSave->cursorY = 0;
162     csSave->cursorVisible = 0;
163     csSave->cursorSet = 0;
164    
165 gbeauche 1.11 // Find and set default gamma table
166     csSave->gammaTable = 0;
167     csSave->maxGammaTableSize = 0;
168 cebix 1.1 set_gamma(csSave, 0);
169    
170     // Install and activate interrupt service
171 gbeauche 1.4 SheepVar32 theServiceID = 0;
172 gbeauche 1.12 VSLNewInterruptService(csSave->regEntryID, FOURCC('v','b','l',' '), theServiceID.addr());
173 gbeauche 1.4 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 gbeauche 1.11 static bool allocate_gamma_table(VidLocals *csSave, uint32 size)
186     {
187     if (size > csSave->maxGammaTableSize) {
188     if (csSave->gammaTable) {
189     Mac_sysfree(csSave->gammaTable);
190     csSave->gammaTable = 0;
191     csSave->maxGammaTableSize = 0;
192     }
193     if ((csSave->gammaTable = Mac_sysalloc(size)) == 0)
194     return false;
195     csSave->maxGammaTableSize = size;
196     }
197     return true;
198     }
199    
200 cebix 1.1 static int16 set_gamma(VidLocals *csSave, uint32 gamma)
201     {
202 gbeauche 1.11 return paramErr;
203    
204     if (gamma == 0) { // Build linear ramp, 256 entries
205    
206     // Allocate new table, if necessary
207     if (!allocate_gamma_table(csSave, SIZEOF_GammaTbl + 256))
208     return memFullErr;
209    
210     // Initialize header
211     WriteMacInt16(csSave->gammaTable + gVersion, 0); // A version 0 style of the GammaTbl structure
212     WriteMacInt16(csSave->gammaTable + gType, 0); // Frame buffer hardware invariant
213     WriteMacInt16(csSave->gammaTable + gFormulaSize, 0); // No formula data, just correction data
214     WriteMacInt16(csSave->gammaTable + gChanCnt, 1); // Apply same correction to Red, Green, & Blue
215     WriteMacInt16(csSave->gammaTable + gDataCnt, 256); // gDataCnt == 2^^gDataWidth
216     WriteMacInt16(csSave->gammaTable + gDataWidth, 8); // 8 bits of significant data per entry
217 cebix 1.1
218     // Build the linear ramp
219 gbeauche 1.11 uint32 p = csSave->gammaTable + gFormulaData;
220     for (int i=0; i<256; i++)
221     WriteMacInt8(p + i, i);
222 cebix 1.1
223 gbeauche 1.11 } else { // User-supplied gamma table
224 cebix 1.1
225 gbeauche 1.11 // Validate header
226     if (ReadMacInt16(gamma + gVersion) != 0)
227 cebix 1.1 return paramErr;
228 gbeauche 1.11 if (ReadMacInt16(gamma + gType) != 0)
229 cebix 1.1 return paramErr;
230 gbeauche 1.11 int chan_cnt = ReadMacInt16(gamma + gChanCnt);
231     if (chan_cnt != 1 && chan_cnt != 3)
232 cebix 1.1 return paramErr;
233 gbeauche 1.11 int data_width = ReadMacInt16(gamma + gDataWidth);
234     if (data_width > 8)
235 cebix 1.1 return paramErr;
236 gbeauche 1.11 int data_cnt = ReadMacInt16(gamma + gDataWidth);
237     if (data_cnt != (1 << data_width))
238 cebix 1.1 return paramErr;
239    
240 gbeauche 1.11 // Allocate new table, if necessary
241     int size = SIZEOF_GammaTbl + ReadMacInt16(gamma + gFormulaSize) + chan_cnt * data_cnt;
242     if (!allocate_gamma_table(csSave, size))
243     return memFullErr;
244 cebix 1.1
245 gbeauche 1.11 // Copy table
246     Mac2Mac_memcpy(csSave->gammaTable, gamma, size);
247 cebix 1.1 }
248     return noErr;
249     }
250    
251     static int16 VideoControl(uint32 pb, VidLocals *csSave)
252     {
253     int16 code = ReadMacInt16(pb + csCode);
254     D(bug("VideoControl %d: ", code));
255     uint32 param = ReadMacInt32(pb + csParam);
256     switch (code) {
257    
258     case cscReset: // VidReset
259     D(bug("VidReset\n"));
260     return controlErr;
261    
262     case cscKillIO: // VidKillIO
263     D(bug("VidKillIO\n"));
264     return controlErr;
265    
266     case cscSetMode: // SetVidMode
267     D(bug("SetVidMode\n"));
268     D(bug("mode:%04x page:%04x \n", ReadMacInt16(param + csMode),
269     ReadMacInt16(param + csPage)));
270     WriteMacInt32(param + csData, csSave->saveData);
271     return video_mode_change(csSave, param);
272    
273     case cscSetEntries: { // SetEntries
274     D(bug("SetEntries\n"));
275     if (VModes[cur_mode].viAppleMode > APPLE_8_BIT) return controlErr;
276 gbeauche 1.6 uint32 s_pal = ReadMacInt32(param + csTable);
277     uint16 start = ReadMacInt16(param + csStart);
278     uint16 count = ReadMacInt16(param + csCount);
279     if (s_pal == 0 || count > 256) return controlErr;
280 cebix 1.1
281     // Preparations for gamma correction
282     bool do_gamma = false;
283     uint8 *red_gamma = NULL;
284     uint8 *green_gamma = NULL;
285     uint8 *blue_gamma = NULL;
286     int gamma_data_width = 0;
287 gbeauche 1.11 if (csSave->gammaTable) {
288     #ifdef __BEOS__
289     // Windows are gamma-corrected by BeOS
290     const bool can_do_gamma = (display_type == DIS_SCREEN);
291     #else
292     const bool can_do_gamma = true;
293     #endif
294     if (can_do_gamma) {
295     uint32 gamma_table = csSave->gammaTable;
296     red_gamma = Mac2HostAddr(gamma_table + gFormulaData + ReadMacInt16(gamma_table + gFormulaSize));
297     int chan_cnt = ReadMacInt16(gamma_table + gChanCnt);
298     if (chan_cnt == 1)
299     green_gamma = blue_gamma = red_gamma;
300     else {
301     int ofs = ReadMacInt16(gamma_table + gDataCnt);
302     green_gamma = red_gamma + ofs;
303     blue_gamma = green_gamma + ofs;
304     }
305     gamma_data_width = ReadMacInt16(gamma_table + gDataWidth);
306     do_gamma = true;
307 cebix 1.1 }
308     }
309    
310     // Set palette
311     rgb_color *d_pal;
312 gbeauche 1.6 if (start == 0xffff) { // Indexed
313 cebix 1.1 for (int i=0; i<=count; i++) {
314 gbeauche 1.6 d_pal = mac_pal + (ReadMacInt16(s_pal + csValue) & 0xff);
315     uint8 red = (uint16)ReadMacInt16(s_pal + csRed) >> 8;
316     uint8 green = (uint16)ReadMacInt16(s_pal + csGreen) >> 8;
317     uint8 blue = (uint16)ReadMacInt16(s_pal + csBlue) >> 8;
318 cebix 1.1 if (csSave->luminanceMapping)
319     red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16;
320     if (do_gamma) {
321     red = red_gamma[red >> (8 - gamma_data_width)];
322     green = green_gamma[green >> (8 - gamma_data_width)];
323     blue = blue_gamma[blue >> (8 - gamma_data_width)];
324     }
325     (*d_pal).red = red;
326     (*d_pal).green = green;
327     (*d_pal).blue = blue;
328 gbeauche 1.6 s_pal += 8;
329 cebix 1.1 }
330 gbeauche 1.6 } else { // Sequential
331     d_pal = mac_pal + start;
332 cebix 1.1 for (int i=0; i<=count; i++) {
333 gbeauche 1.6 uint8 red = (uint16)ReadMacInt16(s_pal + csRed) >> 8;
334     uint8 green = (uint16)ReadMacInt16(s_pal + csGreen) >> 8;
335     uint8 blue = (uint16)ReadMacInt16(s_pal + csBlue) >> 8;
336 cebix 1.1 if (csSave->luminanceMapping)
337     red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16;
338     if (do_gamma) {
339     red = red_gamma[red >> (8 - gamma_data_width)];
340     green = green_gamma[green >> (8 - gamma_data_width)];
341     blue = blue_gamma[blue >> (8 - gamma_data_width)];
342     }
343     (*d_pal).red = red;
344     (*d_pal).green = green;
345     (*d_pal).blue = blue;
346 gbeauche 1.6 d_pal++;
347     s_pal += 8;
348 cebix 1.1 }
349     }
350     video_set_palette();
351     return noErr;
352     }
353    
354 gbeauche 1.11 case cscSetGamma: { // SetGamma
355     uint32 user_table = ReadMacInt32(param + csGTable);
356     D(bug("SetGamma %08x\n", user_table));
357     return set_gamma(csSave, ReadMacInt32(user_table));
358     }
359 cebix 1.1
360     case cscGrayPage: { // GrayPage
361 gbeauche 1.6 D(bug("GrayPage %d\n", ReadMacInt16(param + csPage)));
362     if (ReadMacInt16(param + csPage))
363     return paramErr;
364    
365     uint32 pattern[6] = {
366     0xaaaaaaaa, // 1 bpp
367     0xcccccccc, // 2 bpp
368     0xf0f0f0f0, // 4 bpp
369     0xff00ff00, // 8 bpp
370     0xffff0000, // 16 bpp
371     0xffffffff // 32 bpp
372     };
373     uint32 p = csSave->saveBaseAddr;
374     uint32 pat = pattern[VModes[cur_mode].viAppleMode - APPLE_1_BIT];
375     bool invert = (VModes[cur_mode].viAppleMode == APPLE_32_BIT);
376     for (uint32 y=0; y<VModes[cur_mode].viYsize; y++) {
377     for (uint32 x=0; x<VModes[cur_mode].viRowBytes; x+=4) {
378     WriteMacInt32(p + x, pat);
379     if (invert)
380     pat = ~pat;
381     }
382     p += VModes[cur_mode].viRowBytes;
383     pat = ~pat;
384 cebix 1.1 }
385     return noErr;
386     }
387    
388     case cscSetGray: // SetGray
389     D(bug("SetGray %02x\n", ReadMacInt8(param)));
390     csSave->luminanceMapping = ReadMacInt8(param);
391     return noErr;
392    
393     case cscSetInterrupt: // SetInterrupt
394     D(bug("SetInterrupt\n"));
395     csSave->interruptsEnabled = !ReadMacInt8(param);
396     return noErr;
397    
398     case cscDirectSetEntries: // DirectSetEntries
399     D(bug("DirectSetEntries\n"));
400     return controlErr;
401    
402     case cscSetDefaultMode: // SetDefaultMode
403     D(bug("SetDefaultMode\n"));
404     return controlErr;
405    
406     case cscSwitchMode:
407     D(bug("cscSwitchMode (Display Manager support) \nMode:%02x ID:%04x Page:%d\n",
408     ReadMacInt16(param + csMode), ReadMacInt32(param + csData), ReadMacInt16(param + csPage)));
409     return video_mode_change(csSave, param);
410    
411     case cscSavePreferredConfiguration:
412     D(bug("SavePreferredConfiguration\n"));
413     save_conf_id = ReadMacInt32(param + csData);
414     save_conf_mode = ReadMacInt16(param + csMode);
415     return noErr;
416    
417     case cscSetHardwareCursor: {
418     // D(bug("SetHardwareCursor\n"));
419     csSave->cursorSet = false;
420     bool changed = false;
421    
422     // Get cursor data even on a screen, to set the right cursor image when switching back to a window
423     // Image
424     uint32 cursor = ReadMacInt32(param); // Pointer to CursorImage
425     uint32 pmhandle = ReadMacInt32(cursor + ciCursorPixMap);
426     if (pmhandle == 0 || ReadMacInt32(pmhandle) == 0)
427     return controlErr;
428     uint32 pixmap = ReadMacInt32(pmhandle);
429     if (memcmp(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32)) {
430     memcpy(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32);
431     changed = true;
432     }
433    
434     // Mask
435     uint32 bmhandle = ReadMacInt32(cursor + ciCursorBitMask);
436     if (bmhandle == 0 || ReadMacInt32(bmhandle) == 0)
437     return controlErr;
438     uint32 bitmap = ReadMacInt32(bmhandle);
439     if (memcmp(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32)) {
440     memcpy(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32);
441     changed = true;
442     }
443    
444     // Hotspot (!! this doesn't work)
445     MacCursor[2] = ReadMacInt8(0x885);
446     MacCursor[3] = ReadMacInt8(0x887);
447    
448     // Set new cursor image
449 gbeauche 1.8 if (!video_can_change_cursor())
450 cebix 1.1 return controlErr;
451     if (changed)
452     video_set_cursor();
453    
454     csSave->cursorSet = true;
455     return noErr;
456     }
457    
458     case cscDrawHardwareCursor:
459     // D(bug("DrawHardwareCursor\n"));
460     csSave->cursorX = ReadMacInt32(param + csCursorX);
461     csSave->cursorY = ReadMacInt32(param + csCursorY);
462     csSave->cursorVisible = ReadMacInt32(param + csCursorVisible);
463     return noErr;
464    
465     case 43: { // Driver Gestalt
466     uint32 sel = ReadMacInt32(pb + csParam);
467     D(bug(" driver gestalt %c%c%c%c\n", sel >> 24, sel >> 16, sel >> 8, sel));
468     switch (sel) {
469     case FOURCC('v','e','r','s'):
470     WriteMacInt32(pb + csParam + 4, 0x01008000);
471     break;
472     case FOURCC('i','n','t','f'):
473     WriteMacInt32(pb + csParam + 4, FOURCC('c','a','r','d'));
474     break;
475     case FOURCC('s','y','n','c'):
476     WriteMacInt32(pb + csParam + 4, 0x01000000);
477     break;
478     default:
479     return statusErr;
480     };
481     return noErr;
482     }
483    
484     default:
485     D(bug(" unknown control code %d\n", code));
486     return controlErr;
487     }
488     }
489    
490    
491     /*
492     * Video driver status routine
493     */
494    
495     // Search for given AppleID in mode table
496     static bool has_mode(uint32 id)
497     {
498     VideoInfo *p = VModes;
499     while (p->viType != DIS_INVALID) {
500     if (p->viAppleID == id)
501     return true;
502     p++;
503     }
504     return false;
505     }
506    
507     // Find maximum depth for given AppleID
508     static uint32 max_depth(uint32 id)
509     {
510     uint32 max = APPLE_1_BIT;
511     VideoInfo *p = VModes;
512     while (p->viType != DIS_INVALID) {
513     if (p->viAppleID == id && p->viAppleMode > max)
514     max = p->viAppleMode;
515     p++;
516     }
517     return max;
518     }
519    
520     static int16 VideoStatus(uint32 pb, VidLocals *csSave)
521     {
522     int16 code = ReadMacInt16(pb + csCode);
523     D(bug("VideoStatus %d: ", code));
524     uint32 param = ReadMacInt32(pb + csParam);
525     switch (code) {
526    
527     case cscGetMode: // GetMode
528     D(bug("GetMode\n"));
529     WriteMacInt32(param + csBaseAddr, csSave->saveBaseAddr);
530     WriteMacInt16(param + csMode, csSave->saveMode);
531     WriteMacInt16(param + csPage, csSave->savePage);
532     D(bug("return: mode:%04x page:%04x ", ReadMacInt16(param + csMode),
533     ReadMacInt16(param + csPage)));
534     D(bug("base adress %08lx\n", ReadMacInt32(param + csBaseAddr)));
535     return noErr;
536    
537     case cscGetEntries: { // GetEntries
538     D(bug("GetEntries\n"));
539 gbeauche 1.6 uint32 d_pal = ReadMacInt32(param + csTable);
540     uint16 start = ReadMacInt16(param + csStart);
541     uint16 count = ReadMacInt16(param + csCount);
542 cebix 1.1 rgb_color *s_pal;
543     if ((VModes[cur_mode].viAppleMode == APPLE_32_BIT)||
544     (VModes[cur_mode].viAppleMode == APPLE_16_BIT)) {
545     D(bug("ERROR: GetEntries in direct mode \n"));
546     return statusErr;
547     }
548 gbeauche 1.6
549     if (start == 0xffff) { // Indexed
550 cebix 1.1 for (uint16 i=0;i<count;i++) {
551 gbeauche 1.6 s_pal = mac_pal + (ReadMacInt16(d_pal + csValue) & 0xff);
552     uint8 red = (*s_pal).red;
553     uint8 green = (*s_pal).green;
554     uint8 blue = (*s_pal).blue;
555     WriteMacInt16(d_pal + csRed, red * 0x0101);
556     WriteMacInt16(d_pal + csGreen, green * 0x0101);
557     WriteMacInt16(d_pal + csBlue, blue * 0x0101);
558     d_pal += 8;
559 cebix 1.1 }
560 gbeauche 1.6 } else { // Sequential
561     if (start + count > 255)
562     return paramErr;
563     s_pal = mac_pal + start;
564 cebix 1.1 for (uint16 i=0;i<count;i++) {
565 gbeauche 1.6 uint8 red = (*s_pal).red;
566     uint8 green = (*s_pal).green;
567     uint8 blue = (*s_pal).blue;
568     s_pal++;
569     WriteMacInt16(d_pal + csRed, red * 0x0101);
570     WriteMacInt16(d_pal + csGreen, green * 0x0101);
571     WriteMacInt16(d_pal + csBlue, blue * 0x0101);
572     d_pal += 8;
573 cebix 1.1 }
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 gbeauche 1.7 case APPLE_1152x768:
692     WriteMacInt32(param + csHorizontalPixels, 1152);
693     WriteMacInt32(param + csVerticalLines, 768);
694     WriteMacInt32(param + csRefreshRate, 75<<16);
695     break;
696 cebix 1.1 case APPLE_1152x900:
697     WriteMacInt32(param + csHorizontalPixels, 1152);
698     WriteMacInt32(param + csVerticalLines, 900);
699     WriteMacInt32(param + csRefreshRate, 75<<16);
700     break;
701     case APPLE_1280x1024:
702     WriteMacInt32(param + csHorizontalPixels, 1280);
703     WriteMacInt32(param + csVerticalLines, 1024);
704     WriteMacInt32(param + csRefreshRate, 75<<16);
705     break;
706     case APPLE_1600x1200:
707     WriteMacInt32(param + csHorizontalPixels, 1600);
708     WriteMacInt32(param + csVerticalLines, 1200);
709     WriteMacInt32(param + csRefreshRate, 75<<16);
710     break;
711     }
712     return noErr;
713     }
714    
715     case cscGetVideoParameters: // GetVideoParameters
716     D(bug("GetVideoParameters ID:%08lx Depth:%04x\n",
717     ReadMacInt32(param + csDisplayModeID),
718     ReadMacInt16(param + csDepthMode)));
719    
720     // find right video mode
721     for (int i=0; VModes[i].viType!=DIS_INVALID; i++) {
722     if ((ReadMacInt16(param + csDepthMode) == VModes[i].viAppleMode) &&
723     (ReadMacInt32(param + csDisplayModeID) == VModes[i].viAppleID)) {
724     uint32 vpb = ReadMacInt32(param + csVPBlockPtr);
725     WriteMacInt32(vpb + vpBaseOffset, 0);
726     WriteMacInt16(vpb + vpRowBytes, VModes[i].viRowBytes);
727     WriteMacInt16(vpb + vpBounds, 0);
728     WriteMacInt16(vpb + vpBounds + 2, 0);
729     WriteMacInt16(vpb + vpBounds + 4, VModes[i].viYsize);
730     WriteMacInt16(vpb + vpBounds + 6, VModes[i].viXsize);
731     WriteMacInt16(vpb + vpVersion, 0); // Pixel Map version number
732     WriteMacInt16(vpb + vpPackType, 0);
733     WriteMacInt32(vpb + vpPackSize, 0);
734     WriteMacInt32(vpb + vpHRes, 0x00480000); // horiz res of the device (ppi)
735     WriteMacInt32(vpb + vpVRes, 0x00480000); // vert res of the device (ppi)
736     switch (VModes[i].viAppleMode) {
737     case APPLE_1_BIT:
738     WriteMacInt16(vpb + vpPixelType, 0);
739     WriteMacInt16(vpb + vpPixelSize, 1);
740     WriteMacInt16(vpb + vpCmpCount, 1);
741     WriteMacInt16(vpb + vpCmpSize, 1);
742     WriteMacInt32(param + csDeviceType, 0); // CLUT
743     break;
744     case APPLE_2_BIT:
745     WriteMacInt16(vpb + vpPixelType, 0);
746     WriteMacInt16(vpb + vpPixelSize, 2);
747     WriteMacInt16(vpb + vpCmpCount, 1);
748     WriteMacInt16(vpb + vpCmpSize, 2);
749     WriteMacInt32(param + csDeviceType, 0); // CLUT
750     break;
751     case APPLE_4_BIT:
752     WriteMacInt16(vpb + vpPixelType, 0);
753     WriteMacInt16(vpb + vpPixelSize, 4);
754     WriteMacInt16(vpb + vpCmpCount, 1);
755     WriteMacInt16(vpb + vpCmpSize, 4);
756     WriteMacInt32(param + csDeviceType, 0); // CLUT
757     break;
758     case APPLE_8_BIT:
759     WriteMacInt16(vpb + vpPixelType, 0);
760     WriteMacInt16(vpb + vpPixelSize, 8);
761     WriteMacInt16(vpb + vpCmpCount, 1);
762     WriteMacInt16(vpb + vpCmpSize, 8);
763     WriteMacInt32(param + csDeviceType, 0); // CLUT
764     break;
765     case APPLE_16_BIT:
766     WriteMacInt16(vpb + vpPixelType, 0x10);
767     WriteMacInt16(vpb + vpPixelSize, 16);
768     WriteMacInt16(vpb + vpCmpCount, 3);
769     WriteMacInt16(vpb + vpCmpSize, 5);
770     WriteMacInt32(param + csDeviceType, 2); // DIRECT
771     break;
772     case APPLE_32_BIT:
773     WriteMacInt16(vpb + vpPixelType, 0x10);
774     WriteMacInt16(vpb + vpPixelSize, 32);
775     WriteMacInt16(vpb + vpCmpCount, 3);
776     WriteMacInt16(vpb + vpCmpSize, 8);
777     WriteMacInt32(param + csDeviceType, 2); // DIRECT
778     break;
779     }
780     WriteMacInt32(param + csPageCount, 1);
781     return noErr;
782     }
783     }
784     return paramErr;
785    
786     case cscGetModeTiming:
787     D(bug("GetModeTiming mode %08lx\n", ReadMacInt32(param + csTimingMode)));
788     WriteMacInt32(param + csTimingFormat, kDeclROMtables);
789     WriteMacInt32(param + csTimingFlags, (1<<kModeValid)|(1<<kModeSafe)|(1<<kShowModeNow)); // Mode valid, safe, default and shown in Monitors panel
790     for (int i=0; VModes[i].viType!=DIS_INVALID; i++) {
791     if (ReadMacInt32(param + csTimingMode) == VModes[i].viAppleID) {
792     uint32 timing = timingUnknown;
793     uint32 flags = (1<<kModeValid) | (1<<kShowModeNow);
794     switch (VModes[i].viAppleID) {
795     case APPLE_640x480:
796     timing = timingVESA_640x480_75hz;
797     flags |= (1<<kModeSafe);
798     break;
799     case APPLE_W_640x480:
800     timing = timingVESA_640x480_60hz;
801     flags |= (1<<kModeSafe);
802     break;
803     case APPLE_800x600:
804     timing = timingVESA_800x600_75hz;
805     flags |= (1<<kModeSafe);
806     break;
807     case APPLE_W_800x600:
808     timing = timingVESA_800x600_60hz;
809     flags |= (1<<kModeSafe);
810     break;
811     case APPLE_1024x768:
812     timing = timingVESA_1024x768_75hz;
813 gbeauche 1.7 break;
814     case APPLE_1152x768:
815     timing = timingApple_1152x870_75hz; // FIXME
816 cebix 1.1 break;
817     case APPLE_1152x900:
818     timing = timingApple_1152x870_75hz;
819     break;
820     case APPLE_1280x1024:
821     timing = timingVESA_1280x960_75hz;
822     break;
823     case APPLE_1600x1200:
824     timing = timingVESA_1600x1200_75hz;
825     break;
826     default:
827     timing = timingUnknown;
828     break;
829     }
830     WriteMacInt32(param + csTimingData, timing);
831     WriteMacInt32(param + csTimingFlags, flags);
832     return noErr;
833     }
834     }
835     return paramErr;
836    
837     case cscSupportsHardwareCursor:
838     D(bug("SupportsHardwareCursor\n"));
839     WriteMacInt32(param, 1);
840     return noErr;
841    
842     case cscGetHardwareCursorDrawState:
843     D(bug("GetHardwareCursorDrawState\n"));
844     WriteMacInt32(param + csCursorX, csSave->cursorX);
845     WriteMacInt32(param + csCursorY, csSave->cursorY);
846     WriteMacInt32(param + csCursorVisible, csSave->cursorVisible);
847     WriteMacInt32(param + csCursorSet, csSave->cursorSet);
848     return noErr;
849    
850     default:
851     D(bug(" unknown status code %d\n", code));
852     return statusErr;
853     }
854     }
855    
856    
857     /*
858     * Video driver close routine
859     */
860    
861     static int16 VideoClose(uint32 pb, VidLocals *csSave)
862     {
863     D(bug("VideoClose\n"));
864    
865     // Delete interrupt service
866     csSave->interruptsEnabled = false;
867     VSLDisposeInterruptService(csSave->vslServiceID);
868    
869     return noErr;
870     }
871    
872    
873     /*
874     * Native (PCI) driver entry
875     */
876    
877 gbeauche 1.9 int16 VideoDoDriverIO(uint32 spaceID, uint32 commandID, uint32 commandContents, uint32 commandCode, uint32 commandKind)
878 cebix 1.1 {
879 gbeauche 1.9 // D(bug("VideoDoDriverIO space %08x, command %08x, contents %08x, code %d, kind %d\n", spaceID, commandID, commandContents, commandCode, commandKind));
880 cebix 1.1 int16 err = noErr;
881    
882     switch (commandCode) {
883     case kInitializeCommand:
884     case kReplaceCommand:
885 gbeauche 1.11 if (private_data != NULL) { // Might be left over from a reboot
886     if (private_data->gammaTable)
887     Mac_sysfree(private_data->gammaTable);
888 gbeauche 1.12 if (private_data->regEntryID)
889     Mac_sysfree(private_data->regEntryID);
890 gbeauche 1.11 }
891 cebix 1.1 delete private_data;
892    
893 gbeauche 1.10 iocic_tvect = FindLibSymbol("\021DriverServicesLib", "\023IOCommandIsComplete");
894 cebix 1.1 D(bug("IOCommandIsComplete TVECT at %08lx\n", iocic_tvect));
895     if (iocic_tvect == 0) {
896     printf("FATAL: VideoDoDriverIO(): Can't find IOCommandIsComplete()\n");
897     err = -1;
898     break;
899     }
900 gbeauche 1.10 vslnewis_tvect = FindLibSymbol("\020VideoServicesLib", "\026VSLNewInterruptService");
901 cebix 1.1 D(bug("VSLNewInterruptService TVECT at %08lx\n", vslnewis_tvect));
902     if (vslnewis_tvect == 0) {
903     printf("FATAL: VideoDoDriverIO(): Can't find VSLNewInterruptService()\n");
904     err = -1;
905     break;
906     }
907 gbeauche 1.10 vsldisposeis_tvect = FindLibSymbol("\020VideoServicesLib", "\032VSLDisposeInterruptService");
908 cebix 1.1 D(bug("VSLDisposeInterruptService TVECT at %08lx\n", vsldisposeis_tvect));
909     if (vsldisposeis_tvect == 0) {
910     printf("FATAL: VideoDoDriverIO(): Can't find VSLDisposeInterruptService()\n");
911     err = -1;
912     break;
913     }
914 gbeauche 1.10 vsldois_tvect = FindLibSymbol("\020VideoServicesLib", "\025VSLDoInterruptService");
915 cebix 1.1 D(bug("VSLDoInterruptService TVECT at %08lx\n", vsldois_tvect));
916     if (vsldois_tvect == 0) {
917     printf("FATAL: VideoDoDriverIO(): Can't find VSLDoInterruptService()\n");
918     err = -1;
919     break;
920     }
921 gbeauche 1.10 nqdmisc_tvect = FindLibSymbol("\014InterfaceLib", "\007NQDMisc");
922 cebix 1.1 D(bug("NQDMisc TVECT at %08lx\n", nqdmisc_tvect));
923     if (nqdmisc_tvect == 0) {
924     printf("FATAL: VideoDoDriverIO(): Can't find NQDMisc()\n");
925     err = -1;
926     break;
927     }
928    
929     private_data = new VidLocals;
930 gbeauche 1.11 private_data->gammaTable = 0;
931 gbeauche 1.12 private_data->regEntryID = Mac_sysalloc(sizeof(RegEntryID));
932     if (private_data->regEntryID == 0) {
933     printf("FATAL: VideoDoDriverIO(): Can't allocate service owner\n");
934     err = -1;
935     break;
936     }
937     Mac2Mac_memcpy(private_data->regEntryID, commandContents + 2, 16); // DriverInitInfo.deviceEntry
938 cebix 1.1 private_data->interruptsEnabled = false; // Disable interrupts
939     break;
940    
941     case kFinalizeCommand:
942     case kSupersededCommand:
943 gbeauche 1.12 if (private_data != NULL) {
944     if (private_data->gammaTable)
945     Mac_sysfree(private_data->gammaTable);
946     if (private_data->regEntryID)
947     Mac_sysfree(private_data->regEntryID);
948     }
949 cebix 1.1 delete private_data;
950     private_data = NULL;
951     break;
952    
953     case kOpenCommand:
954 gbeauche 1.9 err = VideoOpen(commandContents, private_data);
955 cebix 1.1 break;
956    
957     case kCloseCommand:
958 gbeauche 1.9 err = VideoClose(commandContents, private_data);
959 cebix 1.1 break;
960    
961     case kControlCommand:
962 gbeauche 1.9 err = VideoControl(commandContents, private_data);
963 cebix 1.1 break;
964    
965     case kStatusCommand:
966 gbeauche 1.9 err = VideoStatus(commandContents, private_data);
967 cebix 1.1 break;
968    
969     case kReadCommand:
970     case kWriteCommand:
971     break;
972    
973     case kKillIOCommand:
974     err = abortErr;
975     break;
976    
977     default:
978     err = paramErr;
979     break;
980     }
981    
982     if (commandKind == kImmediateIOCommandKind)
983     return err;
984     else
985     return IOCommandIsComplete(commandID, err);
986     }