ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/video.cpp
Revision: 1.9
Committed: 2004-11-13T14:09:15Z (19 years, 6 months ago) by gbeauche
Branch: MAIN
Changes since 1.8: +15 -14 lines
Log Message:
Implement Direct Addressing mode similarly to Basilisk II. This is to get
SheepShaver working on OSes that don't support maipping of Low Memory globals
at 0x00000000, e.g. Windows.

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 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->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 gbeauche 1.9 VSLNewInterruptService(Host2MacAddr((uint8 *)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     static int16 set_gamma(VidLocals *csSave, uint32 gamma)
186     {
187 gbeauche 1.9 #warning "FIXME: this code is not little endian aware"
188 cebix 1.1 GammaTbl *clientGamma = (GammaTbl *)gamma;
189     GammaTbl *gammaTable = csSave->gammaTable;
190    
191     if (clientGamma == NULL) {
192    
193     // No gamma table supplied, build linear ramp
194     uint32 linearRampSize = sizeof(GammaTbl) + 256 - 2;
195     uint8 *correctionData;
196    
197     // Allocate new gamma table if existing gamma table is smaller than required.
198     if (linearRampSize > csSave->maxGammaTableSize) {
199     delete[] csSave->gammaTable;
200     csSave->gammaTable = (GammaTbl *)new uint8[linearRampSize];
201     csSave->maxGammaTableSize = linearRampSize;
202     gammaTable = csSave->gammaTable;
203     }
204    
205     gammaTable->gVersion = 0; // A version 0 style of the GammaTbl structure
206     gammaTable->gType = 0; // Frame buffer hardware invariant
207     gammaTable->gFormulaSize = 0; // No formula data, just correction data
208     gammaTable->gChanCnt = 1; // Apply same correction to Red, Green, & Blue
209     gammaTable->gDataCnt = 256; // gDataCnt == 2^^gDataWidth
210     gammaTable->gDataWidth = 8; // 8 bits of significant data per entry
211    
212     // Find the starting address of the correction data. This can be computed by starting at
213     // the address of gFormula[0] and adding the gFormulaSize.
214     correctionData = (uint8 *)((uint32)&gammaTable->gFormulaData[0] + gammaTable->gFormulaSize);
215    
216     // Build the linear ramp
217     for (int i=0; i<gammaTable->gDataCnt; i++)
218     *correctionData++ = i;
219    
220     } else {
221    
222     // User supplied a gamma table, so make sure it is a valid one
223     if (clientGamma->gVersion != 0)
224     return paramErr;
225     if (clientGamma->gType != 0)
226     return paramErr;
227     if ((clientGamma->gChanCnt != 1) && (clientGamma->gChanCnt != 3))
228     return paramErr;
229     if (clientGamma->gDataWidth > 8)
230     return paramErr;
231     if (clientGamma->gDataCnt != (1 << clientGamma->gDataWidth))
232     return paramErr;
233    
234     uint32 tableSize = sizeof(GammaTbl) // fixed size header
235     + clientGamma->gFormulaSize // add formula size
236     + clientGamma->gChanCnt * clientGamma->gDataCnt // assume 1 byte/entry
237     - 2; // correct gFormulaData[0] counted twice
238    
239     // Allocate new gamma table if existing gamma table is smaller than required.
240     if (tableSize > csSave->maxGammaTableSize) {
241     delete[] csSave->gammaTable;
242     csSave->gammaTable = (GammaTbl *)new uint8[tableSize];
243     csSave->maxGammaTableSize = tableSize;
244     gammaTable = csSave->gammaTable;
245     }
246    
247     // Copy gamma table header
248     *gammaTable = *clientGamma;
249    
250     // Copy the formula data (if any)
251     uint8 *newData = (uint8 *)&gammaTable->gFormulaData[0]; // Point to newGamma's formula data
252     uint8 *clientData = (uint8 *)&clientGamma->gFormulaData[0]; // Point to clientGamma's formula data
253     for (int i=0; i<gammaTable->gFormulaSize; i++)
254     *newData++ = *clientData++;
255    
256     // Copy the correction data. Convientiently, after copying the formula data, the 'newData'
257     // pointer and the 'clientData' pointer are pointing to the their respective starting points
258     // of their correction data.
259     for (int i=0; i<gammaTable->gChanCnt; i++)
260     for (int j=0; j<gammaTable->gDataCnt; j++)
261     *newData++ = *clientData++;
262     }
263     return noErr;
264     }
265    
266     static int16 VideoControl(uint32 pb, VidLocals *csSave)
267     {
268     int16 code = ReadMacInt16(pb + csCode);
269     D(bug("VideoControl %d: ", code));
270     uint32 param = ReadMacInt32(pb + csParam);
271     switch (code) {
272    
273     case cscReset: // VidReset
274     D(bug("VidReset\n"));
275     return controlErr;
276    
277     case cscKillIO: // VidKillIO
278     D(bug("VidKillIO\n"));
279     return controlErr;
280    
281     case cscSetMode: // SetVidMode
282     D(bug("SetVidMode\n"));
283     D(bug("mode:%04x page:%04x \n", ReadMacInt16(param + csMode),
284     ReadMacInt16(param + csPage)));
285     WriteMacInt32(param + csData, csSave->saveData);
286     return video_mode_change(csSave, param);
287    
288     case cscSetEntries: { // SetEntries
289     D(bug("SetEntries\n"));
290     if (VModes[cur_mode].viAppleMode > APPLE_8_BIT) return controlErr;
291 gbeauche 1.6 uint32 s_pal = ReadMacInt32(param + csTable);
292     uint16 start = ReadMacInt16(param + csStart);
293     uint16 count = ReadMacInt16(param + csCount);
294     if (s_pal == 0 || count > 256) return controlErr;
295 cebix 1.1
296     // Preparations for gamma correction
297     bool do_gamma = false;
298     uint8 *red_gamma = NULL;
299     uint8 *green_gamma = NULL;
300     uint8 *blue_gamma = NULL;
301     int gamma_data_width = 0;
302     if (display_type == DIS_SCREEN && csSave->gammaTable != NULL) { // Windows are gamma-corrected by BeOS
303     do_gamma = true;
304     GammaTbl *gamma = csSave->gammaTable;
305     gamma_data_width = gamma->gDataWidth;
306     red_gamma = (uint8 *)&gamma->gFormulaData + gamma->gFormulaSize;
307     if (gamma->gChanCnt == 1) {
308     green_gamma = blue_gamma = red_gamma;
309     } else {
310     green_gamma = red_gamma + gamma->gDataCnt;
311     blue_gamma = red_gamma + 2 * gamma->gDataCnt;
312     }
313     }
314    
315     // Set palette
316     rgb_color *d_pal;
317 gbeauche 1.6 if (start == 0xffff) { // Indexed
318 cebix 1.1 for (int i=0; i<=count; i++) {
319 gbeauche 1.6 d_pal = mac_pal + (ReadMacInt16(s_pal + csValue) & 0xff);
320     uint8 red = (uint16)ReadMacInt16(s_pal + csRed) >> 8;
321     uint8 green = (uint16)ReadMacInt16(s_pal + csGreen) >> 8;
322     uint8 blue = (uint16)ReadMacInt16(s_pal + csBlue) >> 8;
323 cebix 1.1 if (csSave->luminanceMapping)
324     red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16;
325     if (do_gamma) {
326     red = red_gamma[red >> (8 - gamma_data_width)];
327     green = green_gamma[green >> (8 - gamma_data_width)];
328     blue = blue_gamma[blue >> (8 - gamma_data_width)];
329     }
330     (*d_pal).red = red;
331     (*d_pal).green = green;
332     (*d_pal).blue = blue;
333 gbeauche 1.6 s_pal += 8;
334 cebix 1.1 }
335 gbeauche 1.6 } else { // Sequential
336     d_pal = mac_pal + start;
337 cebix 1.1 for (int i=0; i<=count; i++) {
338 gbeauche 1.6 uint8 red = (uint16)ReadMacInt16(s_pal + csRed) >> 8;
339     uint8 green = (uint16)ReadMacInt16(s_pal + csGreen) >> 8;
340     uint8 blue = (uint16)ReadMacInt16(s_pal + csBlue) >> 8;
341 cebix 1.1 if (csSave->luminanceMapping)
342     red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16;
343     if (do_gamma) {
344     red = red_gamma[red >> (8 - gamma_data_width)];
345     green = green_gamma[green >> (8 - gamma_data_width)];
346     blue = blue_gamma[blue >> (8 - gamma_data_width)];
347     }
348     (*d_pal).red = red;
349     (*d_pal).green = green;
350     (*d_pal).blue = blue;
351 gbeauche 1.6 d_pal++;
352     s_pal += 8;
353 cebix 1.1 }
354     }
355     video_set_palette();
356     return noErr;
357     }
358    
359     case cscSetGamma: // SetGamma
360     D(bug("SetGamma\n"));
361     return set_gamma(csSave, ReadMacInt32(param));
362    
363     case cscGrayPage: { // GrayPage
364 gbeauche 1.6 D(bug("GrayPage %d\n", ReadMacInt16(param + csPage)));
365     if (ReadMacInt16(param + csPage))
366     return paramErr;
367    
368     uint32 pattern[6] = {
369     0xaaaaaaaa, // 1 bpp
370     0xcccccccc, // 2 bpp
371     0xf0f0f0f0, // 4 bpp
372     0xff00ff00, // 8 bpp
373     0xffff0000, // 16 bpp
374     0xffffffff // 32 bpp
375     };
376     uint32 p = csSave->saveBaseAddr;
377     uint32 pat = pattern[VModes[cur_mode].viAppleMode - APPLE_1_BIT];
378     bool invert = (VModes[cur_mode].viAppleMode == APPLE_32_BIT);
379     for (uint32 y=0; y<VModes[cur_mode].viYsize; y++) {
380     for (uint32 x=0; x<VModes[cur_mode].viRowBytes; x+=4) {
381     WriteMacInt32(p + x, pat);
382     if (invert)
383     pat = ~pat;
384     }
385     p += VModes[cur_mode].viRowBytes;
386     pat = ~pat;
387 cebix 1.1 }
388     return noErr;
389     }
390    
391     case cscSetGray: // SetGray
392     D(bug("SetGray %02x\n", ReadMacInt8(param)));
393     csSave->luminanceMapping = ReadMacInt8(param);
394     return noErr;
395    
396     case cscSetInterrupt: // SetInterrupt
397     D(bug("SetInterrupt\n"));
398     csSave->interruptsEnabled = !ReadMacInt8(param);
399     return noErr;
400    
401     case cscDirectSetEntries: // DirectSetEntries
402     D(bug("DirectSetEntries\n"));
403     return controlErr;
404    
405     case cscSetDefaultMode: // SetDefaultMode
406     D(bug("SetDefaultMode\n"));
407     return controlErr;
408    
409     case cscSwitchMode:
410     D(bug("cscSwitchMode (Display Manager support) \nMode:%02x ID:%04x Page:%d\n",
411     ReadMacInt16(param + csMode), ReadMacInt32(param + csData), ReadMacInt16(param + csPage)));
412     return video_mode_change(csSave, param);
413    
414     case cscSavePreferredConfiguration:
415     D(bug("SavePreferredConfiguration\n"));
416     save_conf_id = ReadMacInt32(param + csData);
417     save_conf_mode = ReadMacInt16(param + csMode);
418     return noErr;
419    
420     case cscSetHardwareCursor: {
421     // D(bug("SetHardwareCursor\n"));
422     csSave->cursorSet = false;
423     bool changed = false;
424    
425     // Get cursor data even on a screen, to set the right cursor image when switching back to a window
426     // Image
427     uint32 cursor = ReadMacInt32(param); // Pointer to CursorImage
428     uint32 pmhandle = ReadMacInt32(cursor + ciCursorPixMap);
429     if (pmhandle == 0 || ReadMacInt32(pmhandle) == 0)
430     return controlErr;
431     uint32 pixmap = ReadMacInt32(pmhandle);
432     if (memcmp(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32)) {
433     memcpy(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32);
434     changed = true;
435     }
436    
437     // Mask
438     uint32 bmhandle = ReadMacInt32(cursor + ciCursorBitMask);
439     if (bmhandle == 0 || ReadMacInt32(bmhandle) == 0)
440     return controlErr;
441     uint32 bitmap = ReadMacInt32(bmhandle);
442     if (memcmp(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32)) {
443     memcpy(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32);
444     changed = true;
445     }
446    
447     // Hotspot (!! this doesn't work)
448     MacCursor[2] = ReadMacInt8(0x885);
449     MacCursor[3] = ReadMacInt8(0x887);
450    
451     // Set new cursor image
452 gbeauche 1.8 if (!video_can_change_cursor())
453 cebix 1.1 return controlErr;
454     if (changed)
455     video_set_cursor();
456    
457     csSave->cursorSet = true;
458     return noErr;
459     }
460    
461     case cscDrawHardwareCursor:
462     // D(bug("DrawHardwareCursor\n"));
463     csSave->cursorX = ReadMacInt32(param + csCursorX);
464     csSave->cursorY = ReadMacInt32(param + csCursorY);
465     csSave->cursorVisible = ReadMacInt32(param + csCursorVisible);
466     return noErr;
467    
468     case 43: { // Driver Gestalt
469     uint32 sel = ReadMacInt32(pb + csParam);
470     D(bug(" driver gestalt %c%c%c%c\n", sel >> 24, sel >> 16, sel >> 8, sel));
471     switch (sel) {
472     case FOURCC('v','e','r','s'):
473     WriteMacInt32(pb + csParam + 4, 0x01008000);
474     break;
475     case FOURCC('i','n','t','f'):
476     WriteMacInt32(pb + csParam + 4, FOURCC('c','a','r','d'));
477     break;
478     case FOURCC('s','y','n','c'):
479     WriteMacInt32(pb + csParam + 4, 0x01000000);
480     break;
481     default:
482     return statusErr;
483     };
484     return noErr;
485     }
486    
487     default:
488     D(bug(" unknown control code %d\n", code));
489     return controlErr;
490     }
491     }
492    
493    
494     /*
495     * Video driver status routine
496     */
497    
498     // Search for given AppleID in mode table
499     static bool has_mode(uint32 id)
500     {
501     VideoInfo *p = VModes;
502     while (p->viType != DIS_INVALID) {
503     if (p->viAppleID == id)
504     return true;
505     p++;
506     }
507     return false;
508     }
509    
510     // Find maximum depth for given AppleID
511     static uint32 max_depth(uint32 id)
512     {
513     uint32 max = APPLE_1_BIT;
514     VideoInfo *p = VModes;
515     while (p->viType != DIS_INVALID) {
516     if (p->viAppleID == id && p->viAppleMode > max)
517     max = p->viAppleMode;
518     p++;
519     }
520     return max;
521     }
522    
523     static int16 VideoStatus(uint32 pb, VidLocals *csSave)
524     {
525     int16 code = ReadMacInt16(pb + csCode);
526     D(bug("VideoStatus %d: ", code));
527     uint32 param = ReadMacInt32(pb + csParam);
528     switch (code) {
529    
530     case cscGetMode: // GetMode
531     D(bug("GetMode\n"));
532     WriteMacInt32(param + csBaseAddr, csSave->saveBaseAddr);
533     WriteMacInt16(param + csMode, csSave->saveMode);
534     WriteMacInt16(param + csPage, csSave->savePage);
535     D(bug("return: mode:%04x page:%04x ", ReadMacInt16(param + csMode),
536     ReadMacInt16(param + csPage)));
537     D(bug("base adress %08lx\n", ReadMacInt32(param + csBaseAddr)));
538     return noErr;
539    
540     case cscGetEntries: { // GetEntries
541     D(bug("GetEntries\n"));
542 gbeauche 1.6 uint32 d_pal = ReadMacInt32(param + csTable);
543     uint16 start = ReadMacInt16(param + csStart);
544     uint16 count = ReadMacInt16(param + csCount);
545 cebix 1.1 rgb_color *s_pal;
546     if ((VModes[cur_mode].viAppleMode == APPLE_32_BIT)||
547     (VModes[cur_mode].viAppleMode == APPLE_16_BIT)) {
548     D(bug("ERROR: GetEntries in direct mode \n"));
549     return statusErr;
550     }
551 gbeauche 1.6
552     if (start == 0xffff) { // Indexed
553 cebix 1.1 for (uint16 i=0;i<count;i++) {
554 gbeauche 1.6 s_pal = mac_pal + (ReadMacInt16(d_pal + csValue) & 0xff);
555     uint8 red = (*s_pal).red;
556     uint8 green = (*s_pal).green;
557     uint8 blue = (*s_pal).blue;
558     WriteMacInt16(d_pal + csRed, red * 0x0101);
559     WriteMacInt16(d_pal + csGreen, green * 0x0101);
560     WriteMacInt16(d_pal + csBlue, blue * 0x0101);
561     d_pal += 8;
562 cebix 1.1 }
563 gbeauche 1.6 } else { // Sequential
564     if (start + count > 255)
565     return paramErr;
566     s_pal = mac_pal + start;
567 cebix 1.1 for (uint16 i=0;i<count;i++) {
568 gbeauche 1.6 uint8 red = (*s_pal).red;
569     uint8 green = (*s_pal).green;
570     uint8 blue = (*s_pal).blue;
571     s_pal++;
572     WriteMacInt16(d_pal + csRed, red * 0x0101);
573     WriteMacInt16(d_pal + csGreen, green * 0x0101);
574     WriteMacInt16(d_pal + csBlue, blue * 0x0101);
575     d_pal += 8;
576 cebix 1.1 }
577     };
578     return noErr;
579     }
580    
581     case cscGetPageCnt: // GetPage
582     D(bug("GetPage\n"));
583     WriteMacInt16(param + csPage, 1);
584     return noErr;
585    
586     case cscGetPageBase: // GetPageBase
587     D(bug("GetPageBase\n"));
588     WriteMacInt32(param + csBaseAddr, csSave->saveBaseAddr);
589     return noErr;
590    
591     case cscGetGray: // GetGray
592     D(bug("GetGray\n"));
593     WriteMacInt8(param, csSave->luminanceMapping ? 1 : 0);
594     return noErr;
595    
596     case cscGetInterrupt: // GetInterrupt
597     D(bug("GetInterrupt\n"));
598     WriteMacInt8(param, csSave->interruptsEnabled ? 0 : 1);
599     return noErr;
600    
601     case cscGetGamma: // GetGamma
602     D(bug("GetGamma\n"));
603     WriteMacInt32(param, (uint32)csSave->gammaTable);
604     return statusErr;
605    
606     case cscGetDefaultMode: // GetDefaultMode
607     D(bug("GetDefaultMode\n"));
608     return statusErr;
609    
610     case cscGetCurMode: // GetCurMode
611     D(bug("GetCurMode\n"));
612     WriteMacInt16(param + csMode, csSave->saveMode);
613     WriteMacInt32(param + csData, csSave->saveData);
614     WriteMacInt16(param + csPage, csSave->savePage);
615     WriteMacInt32(param + csBaseAddr, csSave->saveBaseAddr);
616    
617     D(bug("return: mode:%04x ID:%08lx page:%04x ", ReadMacInt16(param + csMode),
618     ReadMacInt32(param + csData), ReadMacInt16(param + csPage)));
619     D(bug("base adress %08lx\n", ReadMacInt32(param + csBaseAddr)));
620     return noErr;
621    
622     case cscGetConnection: // GetConnection
623     D(bug("GetConnection\n"));
624     WriteMacInt16(param + csDisplayType, kMultiModeCRT3Connect);
625     WriteMacInt8(param + csConnectTaggedType, 6);
626     WriteMacInt8(param + csConnectTaggedData, 0x23);
627     WriteMacInt32(param + csConnectFlags, (1<<kAllModesValid)|(1<<kAllModesSafe));
628     WriteMacInt32(param + csDisplayComponent, 0);
629     return noErr;
630    
631     case cscGetModeBaseAddress:
632     D(bug("GetModeBaseAddress (obsolete !) \n"));
633     return statusErr;
634    
635     case cscGetPreferredConfiguration:
636     D(bug("GetPreferredConfiguration \n"));
637     WriteMacInt16(param + csMode, save_conf_mode);
638     WriteMacInt32(param + csData, save_conf_id);
639     return noErr;
640    
641     case cscGetNextResolution: {
642     D(bug("GetNextResolution \n"));
643     int work_id = ReadMacInt32(param + csPreviousDisplayModeID);
644     switch (work_id) {
645     case kDisplayModeIDCurrent:
646     work_id = csSave->saveData;
647     break;
648     case kDisplayModeIDFindFirstResolution:
649     work_id = APPLE_ID_MIN;
650     while (!has_mode(work_id))
651     work_id ++;
652     break;
653     default:
654     if (!has_mode(work_id))
655     return paramErr;
656     work_id++;
657     while (!has_mode(work_id)) {
658     work_id++;
659     if (work_id > APPLE_ID_MAX) {
660     WriteMacInt32(param + csRIDisplayModeID, kDisplayModeIDNoMoreResolutions);
661     return noErr;
662     }
663     }
664     break;
665     }
666     WriteMacInt32(param + csRIDisplayModeID, work_id);
667     WriteMacInt16(param + csMaxDepthMode, max_depth(work_id));
668     switch (work_id) {
669     case APPLE_640x480:
670     WriteMacInt32(param + csHorizontalPixels, 640);
671     WriteMacInt32(param + csVerticalLines, 480);
672     WriteMacInt32(param + csRefreshRate, 75<<16);
673     break;
674     case APPLE_W_640x480:
675     WriteMacInt32(param + csHorizontalPixels, 640);
676     WriteMacInt32(param + csVerticalLines, 480);
677     WriteMacInt32(param + csRefreshRate, 60<<16);
678     break;
679     case APPLE_800x600:
680     WriteMacInt32(param + csHorizontalPixels, 800);
681     WriteMacInt32(param + csVerticalLines, 600);
682     WriteMacInt32(param + csRefreshRate, 75<<16);
683     break;
684     case APPLE_W_800x600:
685     WriteMacInt32(param + csHorizontalPixels, 800);
686     WriteMacInt32(param + csVerticalLines, 600);
687     WriteMacInt32(param + csRefreshRate, 60<<16);
688     break;
689     case APPLE_1024x768:
690     WriteMacInt32(param + csHorizontalPixels, 1024);
691     WriteMacInt32(param + csVerticalLines, 768);
692     WriteMacInt32(param + csRefreshRate, 75<<16);
693     break;
694 gbeauche 1.7 case APPLE_1152x768:
695     WriteMacInt32(param + csHorizontalPixels, 1152);
696     WriteMacInt32(param + csVerticalLines, 768);
697     WriteMacInt32(param + csRefreshRate, 75<<16);
698     break;
699 cebix 1.1 case APPLE_1152x900:
700     WriteMacInt32(param + csHorizontalPixels, 1152);
701     WriteMacInt32(param + csVerticalLines, 900);
702     WriteMacInt32(param + csRefreshRate, 75<<16);
703     break;
704     case APPLE_1280x1024:
705     WriteMacInt32(param + csHorizontalPixels, 1280);
706     WriteMacInt32(param + csVerticalLines, 1024);
707     WriteMacInt32(param + csRefreshRate, 75<<16);
708     break;
709     case APPLE_1600x1200:
710     WriteMacInt32(param + csHorizontalPixels, 1600);
711     WriteMacInt32(param + csVerticalLines, 1200);
712     WriteMacInt32(param + csRefreshRate, 75<<16);
713     break;
714     }
715     return noErr;
716     }
717    
718     case cscGetVideoParameters: // GetVideoParameters
719     D(bug("GetVideoParameters ID:%08lx Depth:%04x\n",
720     ReadMacInt32(param + csDisplayModeID),
721     ReadMacInt16(param + csDepthMode)));
722    
723     // find right video mode
724     for (int i=0; VModes[i].viType!=DIS_INVALID; i++) {
725     if ((ReadMacInt16(param + csDepthMode) == VModes[i].viAppleMode) &&
726     (ReadMacInt32(param + csDisplayModeID) == VModes[i].viAppleID)) {
727     uint32 vpb = ReadMacInt32(param + csVPBlockPtr);
728     WriteMacInt32(vpb + vpBaseOffset, 0);
729     WriteMacInt16(vpb + vpRowBytes, VModes[i].viRowBytes);
730     WriteMacInt16(vpb + vpBounds, 0);
731     WriteMacInt16(vpb + vpBounds + 2, 0);
732     WriteMacInt16(vpb + vpBounds + 4, VModes[i].viYsize);
733     WriteMacInt16(vpb + vpBounds + 6, VModes[i].viXsize);
734     WriteMacInt16(vpb + vpVersion, 0); // Pixel Map version number
735     WriteMacInt16(vpb + vpPackType, 0);
736     WriteMacInt32(vpb + vpPackSize, 0);
737     WriteMacInt32(vpb + vpHRes, 0x00480000); // horiz res of the device (ppi)
738     WriteMacInt32(vpb + vpVRes, 0x00480000); // vert res of the device (ppi)
739     switch (VModes[i].viAppleMode) {
740     case APPLE_1_BIT:
741     WriteMacInt16(vpb + vpPixelType, 0);
742     WriteMacInt16(vpb + vpPixelSize, 1);
743     WriteMacInt16(vpb + vpCmpCount, 1);
744     WriteMacInt16(vpb + vpCmpSize, 1);
745     WriteMacInt32(param + csDeviceType, 0); // CLUT
746     break;
747     case APPLE_2_BIT:
748     WriteMacInt16(vpb + vpPixelType, 0);
749     WriteMacInt16(vpb + vpPixelSize, 2);
750     WriteMacInt16(vpb + vpCmpCount, 1);
751     WriteMacInt16(vpb + vpCmpSize, 2);
752     WriteMacInt32(param + csDeviceType, 0); // CLUT
753     break;
754     case APPLE_4_BIT:
755     WriteMacInt16(vpb + vpPixelType, 0);
756     WriteMacInt16(vpb + vpPixelSize, 4);
757     WriteMacInt16(vpb + vpCmpCount, 1);
758     WriteMacInt16(vpb + vpCmpSize, 4);
759     WriteMacInt32(param + csDeviceType, 0); // CLUT
760     break;
761     case APPLE_8_BIT:
762     WriteMacInt16(vpb + vpPixelType, 0);
763     WriteMacInt16(vpb + vpPixelSize, 8);
764     WriteMacInt16(vpb + vpCmpCount, 1);
765     WriteMacInt16(vpb + vpCmpSize, 8);
766     WriteMacInt32(param + csDeviceType, 0); // CLUT
767     break;
768     case APPLE_16_BIT:
769     WriteMacInt16(vpb + vpPixelType, 0x10);
770     WriteMacInt16(vpb + vpPixelSize, 16);
771     WriteMacInt16(vpb + vpCmpCount, 3);
772     WriteMacInt16(vpb + vpCmpSize, 5);
773     WriteMacInt32(param + csDeviceType, 2); // DIRECT
774     break;
775     case APPLE_32_BIT:
776     WriteMacInt16(vpb + vpPixelType, 0x10);
777     WriteMacInt16(vpb + vpPixelSize, 32);
778     WriteMacInt16(vpb + vpCmpCount, 3);
779     WriteMacInt16(vpb + vpCmpSize, 8);
780     WriteMacInt32(param + csDeviceType, 2); // DIRECT
781     break;
782     }
783     WriteMacInt32(param + csPageCount, 1);
784     return noErr;
785     }
786     }
787     return paramErr;
788    
789     case cscGetModeTiming:
790     D(bug("GetModeTiming mode %08lx\n", ReadMacInt32(param + csTimingMode)));
791     WriteMacInt32(param + csTimingFormat, kDeclROMtables);
792     WriteMacInt32(param + csTimingFlags, (1<<kModeValid)|(1<<kModeSafe)|(1<<kShowModeNow)); // Mode valid, safe, default and shown in Monitors panel
793     for (int i=0; VModes[i].viType!=DIS_INVALID; i++) {
794     if (ReadMacInt32(param + csTimingMode) == VModes[i].viAppleID) {
795     uint32 timing = timingUnknown;
796     uint32 flags = (1<<kModeValid) | (1<<kShowModeNow);
797     switch (VModes[i].viAppleID) {
798     case APPLE_640x480:
799     timing = timingVESA_640x480_75hz;
800     flags |= (1<<kModeSafe);
801     break;
802     case APPLE_W_640x480:
803     timing = timingVESA_640x480_60hz;
804     flags |= (1<<kModeSafe);
805     break;
806     case APPLE_800x600:
807     timing = timingVESA_800x600_75hz;
808     flags |= (1<<kModeSafe);
809     break;
810     case APPLE_W_800x600:
811     timing = timingVESA_800x600_60hz;
812     flags |= (1<<kModeSafe);
813     break;
814     case APPLE_1024x768:
815     timing = timingVESA_1024x768_75hz;
816 gbeauche 1.7 break;
817     case APPLE_1152x768:
818     timing = timingApple_1152x870_75hz; // FIXME
819 cebix 1.1 break;
820     case APPLE_1152x900:
821     timing = timingApple_1152x870_75hz;
822     break;
823     case APPLE_1280x1024:
824     timing = timingVESA_1280x960_75hz;
825     break;
826     case APPLE_1600x1200:
827     timing = timingVESA_1600x1200_75hz;
828     break;
829     default:
830     timing = timingUnknown;
831     break;
832     }
833     WriteMacInt32(param + csTimingData, timing);
834     WriteMacInt32(param + csTimingFlags, flags);
835     return noErr;
836     }
837     }
838     return paramErr;
839    
840     case cscSupportsHardwareCursor:
841     D(bug("SupportsHardwareCursor\n"));
842     WriteMacInt32(param, 1);
843     return noErr;
844    
845     case cscGetHardwareCursorDrawState:
846     D(bug("GetHardwareCursorDrawState\n"));
847     WriteMacInt32(param + csCursorX, csSave->cursorX);
848     WriteMacInt32(param + csCursorY, csSave->cursorY);
849     WriteMacInt32(param + csCursorVisible, csSave->cursorVisible);
850     WriteMacInt32(param + csCursorSet, csSave->cursorSet);
851     return noErr;
852    
853     default:
854     D(bug(" unknown status code %d\n", code));
855     return statusErr;
856     }
857     }
858    
859    
860     /*
861     * Video driver close routine
862     */
863    
864     static int16 VideoClose(uint32 pb, VidLocals *csSave)
865     {
866     D(bug("VideoClose\n"));
867    
868     // Delete interrupt service
869     csSave->interruptsEnabled = false;
870     VSLDisposeInterruptService(csSave->vslServiceID);
871    
872     return noErr;
873     }
874    
875    
876     /*
877     * Native (PCI) driver entry
878     */
879    
880 gbeauche 1.9 int16 VideoDoDriverIO(uint32 spaceID, uint32 commandID, uint32 commandContents, uint32 commandCode, uint32 commandKind)
881 cebix 1.1 {
882 gbeauche 1.9 // D(bug("VideoDoDriverIO space %08x, command %08x, contents %08x, code %d, kind %d\n", spaceID, commandID, commandContents, commandCode, commandKind));
883 cebix 1.1 int16 err = noErr;
884    
885     switch (commandCode) {
886     case kInitializeCommand:
887     case kReplaceCommand:
888     if (private_data != NULL) // Might be left over from a reboot
889     delete private_data->gammaTable;
890     delete private_data;
891    
892     iocic_tvect = (uint32)FindLibSymbol("\021DriverServicesLib", "\023IOCommandIsComplete");
893     D(bug("IOCommandIsComplete TVECT at %08lx\n", iocic_tvect));
894     if (iocic_tvect == 0) {
895     printf("FATAL: VideoDoDriverIO(): Can't find IOCommandIsComplete()\n");
896     err = -1;
897     break;
898     }
899     vslnewis_tvect = (uint32)FindLibSymbol("\020VideoServicesLib", "\026VSLNewInterruptService");
900     D(bug("VSLNewInterruptService TVECT at %08lx\n", vslnewis_tvect));
901     if (vslnewis_tvect == 0) {
902     printf("FATAL: VideoDoDriverIO(): Can't find VSLNewInterruptService()\n");
903     err = -1;
904     break;
905     }
906     vsldisposeis_tvect = (uint32)FindLibSymbol("\020VideoServicesLib", "\032VSLDisposeInterruptService");
907     D(bug("VSLDisposeInterruptService TVECT at %08lx\n", vsldisposeis_tvect));
908     if (vsldisposeis_tvect == 0) {
909     printf("FATAL: VideoDoDriverIO(): Can't find VSLDisposeInterruptService()\n");
910     err = -1;
911     break;
912     }
913     vsldois_tvect = (uint32)FindLibSymbol("\020VideoServicesLib", "\025VSLDoInterruptService");
914     D(bug("VSLDoInterruptService TVECT at %08lx\n", vsldois_tvect));
915     if (vsldois_tvect == 0) {
916     printf("FATAL: VideoDoDriverIO(): Can't find VSLDoInterruptService()\n");
917     err = -1;
918     break;
919     }
920     nqdmisc_tvect = (uint32)FindLibSymbol("\014InterfaceLib", "\007NQDMisc");
921     D(bug("NQDMisc TVECT at %08lx\n", nqdmisc_tvect));
922     if (nqdmisc_tvect == 0) {
923     printf("FATAL: VideoDoDriverIO(): Can't find NQDMisc()\n");
924     err = -1;
925     break;
926     }
927    
928     private_data = new VidLocals;
929     private_data->gammaTable = NULL;
930 gbeauche 1.9 Mac2Host_memcpy(&private_data->regEntryID, commandContents + 2, 16); // DriverInitInfo.deviceEntry
931 cebix 1.1 private_data->interruptsEnabled = false; // Disable interrupts
932     break;
933    
934     case kFinalizeCommand:
935     case kSupersededCommand:
936     if (private_data != NULL)
937     delete private_data->gammaTable;
938     delete private_data;
939     private_data = NULL;
940     break;
941    
942     case kOpenCommand:
943 gbeauche 1.9 err = VideoOpen(commandContents, private_data);
944 cebix 1.1 break;
945    
946     case kCloseCommand:
947 gbeauche 1.9 err = VideoClose(commandContents, private_data);
948 cebix 1.1 break;
949    
950     case kControlCommand:
951 gbeauche 1.9 err = VideoControl(commandContents, private_data);
952 cebix 1.1 break;
953    
954     case kStatusCommand:
955 gbeauche 1.9 err = VideoStatus(commandContents, private_data);
956 cebix 1.1 break;
957    
958     case kReadCommand:
959     case kWriteCommand:
960     break;
961    
962     case kKillIOCommand:
963     err = abortErr;
964     break;
965    
966     default:
967     err = paramErr;
968     break;
969     }
970    
971     if (commandKind == kImmediateIOCommandKind)
972     return err;
973     else
974     return IOCommandIsComplete(commandID, err);
975     }