1 |
cebix |
1.1 |
/* |
2 |
|
|
* video.cpp - Video/graphics emulation |
3 |
|
|
* |
4 |
gbeauche |
1.15 |
* SheepShaver (C) 1997-2008 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 |
|
|
*/ |
25 |
|
|
|
26 |
|
|
#include <stdio.h> |
27 |
|
|
#include <string.h> |
28 |
|
|
|
29 |
|
|
#include "sysdeps.h" |
30 |
|
|
#include "video.h" |
31 |
|
|
#include "video_defs.h" |
32 |
|
|
#include "main.h" |
33 |
|
|
#include "adb.h" |
34 |
|
|
#include "macos_util.h" |
35 |
|
|
#include "user_strings.h" |
36 |
|
|
#include "version.h" |
37 |
gbeauche |
1.4 |
#include "thunks.h" |
38 |
cebix |
1.1 |
|
39 |
|
|
#define DEBUG 0 |
40 |
|
|
#include "debug.h" |
41 |
|
|
|
42 |
|
|
|
43 |
|
|
// Global variables |
44 |
|
|
bool video_activated = false; // Flag: video display activated, mouse and keyboard data valid |
45 |
|
|
uint32 screen_base = 0; // Frame buffer base address |
46 |
|
|
int cur_mode; // Number of current video mode (index in VModes array) |
47 |
|
|
int display_type = DIS_INVALID; // Current display type |
48 |
|
|
rgb_color mac_pal[256]; |
49 |
|
|
uint8 remap_mac_be[256]; |
50 |
|
|
uint8 MacCursor[68] = {16, 1}; // Mac cursor image |
51 |
|
|
|
52 |
|
|
|
53 |
|
|
bool keyfile_valid; // Flag: Keyfile is valid, enable full-screen modes |
54 |
|
|
|
55 |
|
|
|
56 |
|
|
/* |
57 |
|
|
* Video mode information (constructed by VideoInit()) |
58 |
|
|
*/ |
59 |
|
|
|
60 |
|
|
struct VideoInfo VModes[64]; |
61 |
|
|
|
62 |
|
|
|
63 |
|
|
/* |
64 |
|
|
* Driver local variables |
65 |
|
|
*/ |
66 |
|
|
|
67 |
|
|
VidLocals *private_data = NULL; // Pointer to driver local variables (there is only one display, so this is ok) |
68 |
|
|
|
69 |
|
|
static long save_conf_id = APPLE_W_640x480; |
70 |
|
|
static long save_conf_mode = APPLE_8_BIT; |
71 |
|
|
|
72 |
|
|
|
73 |
|
|
// Function pointers of imported functions |
74 |
|
|
typedef int16 (*iocic_ptr)(void *, int16); |
75 |
|
|
static uint32 iocic_tvect = 0; |
76 |
gbeauche |
1.9 |
static inline int16 IOCommandIsComplete(uintptr arg1, int16 arg2) |
77 |
cebix |
1.1 |
{ |
78 |
gbeauche |
1.9 |
return (int16)CallMacOS2(iocic_ptr, iocic_tvect, (void *)arg1, arg2); |
79 |
cebix |
1.1 |
} |
80 |
|
|
typedef int16 (*vslnewis_ptr)(void *, uint32, uint32 *); |
81 |
|
|
static uint32 vslnewis_tvect = 0; |
82 |
gbeauche |
1.9 |
static inline int16 VSLNewInterruptService(uintptr arg1, uint32 arg2, uintptr arg3) |
83 |
cebix |
1.1 |
{ |
84 |
gbeauche |
1.9 |
return (int16)CallMacOS3(vslnewis_ptr, vslnewis_tvect, (void *)arg1, arg2, (uint32 *)arg3); |
85 |
cebix |
1.1 |
} |
86 |
|
|
typedef int16 (*vsldisposeis_ptr)(uint32); |
87 |
|
|
static uint32 vsldisposeis_tvect = 0; |
88 |
|
|
static inline int16 VSLDisposeInterruptService(uint32 arg1) |
89 |
|
|
{ |
90 |
|
|
return (int16)CallMacOS1(vsldisposeis_ptr, vsldisposeis_tvect, arg1); |
91 |
|
|
} |
92 |
|
|
typedef int16 (*vsldois_ptr)(uint32); |
93 |
|
|
static uint32 vsldois_tvect = 0; |
94 |
|
|
int16 VSLDoInterruptService(uint32 arg1) |
95 |
|
|
{ |
96 |
|
|
return (int16)CallMacOS1(vsldois_ptr, vsldois_tvect, arg1); |
97 |
|
|
} |
98 |
|
|
typedef void (*nqdmisc_ptr)(uint32, void *); |
99 |
|
|
static uint32 nqdmisc_tvect = 0; |
100 |
gbeauche |
1.9 |
void NQDMisc(uint32 arg1, uintptr arg2) |
101 |
cebix |
1.1 |
{ |
102 |
gbeauche |
1.9 |
CallMacOS2(nqdmisc_ptr, nqdmisc_tvect, arg1, (void *)arg2); |
103 |
cebix |
1.1 |
} |
104 |
|
|
|
105 |
|
|
|
106 |
|
|
// Prototypes |
107 |
|
|
static int16 set_gamma(VidLocals *csSave, uint32 gamma); |
108 |
|
|
|
109 |
|
|
|
110 |
|
|
/* |
111 |
|
|
* Tell whether window/screen is activated or not (for mouse/keyboard polling) |
112 |
|
|
*/ |
113 |
|
|
|
114 |
|
|
bool VideoActivated(void) |
115 |
|
|
{ |
116 |
|
|
return video_activated; |
117 |
|
|
} |
118 |
|
|
|
119 |
|
|
|
120 |
|
|
/* |
121 |
|
|
* Create RGB snapshot of current screen |
122 |
|
|
*/ |
123 |
|
|
|
124 |
|
|
bool VideoSnapshot(int xsize, int ysize, uint8 *p) |
125 |
|
|
{ |
126 |
|
|
if (display_type == DIS_WINDOW) { |
127 |
|
|
uint8 *screen = (uint8 *)private_data->saveBaseAddr; |
128 |
|
|
uint32 row_bytes = VModes[cur_mode].viRowBytes; |
129 |
|
|
uint32 y2size = VModes[cur_mode].viYsize; |
130 |
|
|
uint32 x2size = VModes[cur_mode].viXsize; |
131 |
|
|
for (int j=0;j<ysize;j++) { |
132 |
|
|
for (int i=0;i<xsize;i++) { |
133 |
|
|
*p++ = mac_pal[screen[uint32(float(j)*float(y2size)/float(ysize))*row_bytes+uint32(float(i)*float(x2size)/float(xsize))]].red; |
134 |
|
|
*p++ = mac_pal[screen[uint32(float(j)*float(y2size)/float(ysize))*row_bytes+uint32(float(i)*float(x2size)/float(xsize))]].green; |
135 |
|
|
*p++ = mac_pal[screen[uint32(float(j)*float(y2size)/float(ysize))*row_bytes+uint32(float(i)*float(x2size)/float(xsize))]].blue; |
136 |
|
|
} |
137 |
|
|
} |
138 |
|
|
return true; |
139 |
|
|
} |
140 |
|
|
return false; |
141 |
|
|
} |
142 |
|
|
|
143 |
|
|
|
144 |
|
|
/* |
145 |
asvitkine |
1.16 |
* Determine whether we should use the hardware or software cursor, and return true for the former, false for the latter. |
146 |
|
|
* Currently we use the hardware cursor if we can, but perhaps this can be made a preference someday. |
147 |
|
|
*/ |
148 |
|
|
|
149 |
|
|
static bool UseHardwareCursor(void) |
150 |
|
|
{ |
151 |
|
|
return video_can_change_cursor(); |
152 |
|
|
} |
153 |
|
|
|
154 |
|
|
|
155 |
|
|
/* |
156 |
cebix |
1.1 |
* Video driver open routine |
157 |
|
|
*/ |
158 |
|
|
|
159 |
|
|
static int16 VideoOpen(uint32 pb, VidLocals *csSave) |
160 |
|
|
{ |
161 |
|
|
D(bug("Video Open\n")); |
162 |
|
|
|
163 |
|
|
// Set up VidLocals |
164 |
|
|
csSave->saveBaseAddr = screen_base; |
165 |
|
|
csSave->saveData = VModes[cur_mode].viAppleID;// First mode ... |
166 |
|
|
csSave->saveMode = VModes[cur_mode].viAppleMode; |
167 |
|
|
csSave->savePage = 0; |
168 |
|
|
csSave->saveVidParms = 0; // Add the right table |
169 |
|
|
csSave->luminanceMapping = false; |
170 |
asvitkine |
1.16 |
csSave->cursorHardware = UseHardwareCursor(); |
171 |
cebix |
1.1 |
csSave->cursorX = 0; |
172 |
|
|
csSave->cursorY = 0; |
173 |
|
|
csSave->cursorVisible = 0; |
174 |
|
|
csSave->cursorSet = 0; |
175 |
asvitkine |
1.16 |
csSave->cursorHotFlag = false; |
176 |
|
|
csSave->cursorHotX = 0; |
177 |
|
|
csSave->cursorHotY = 0; |
178 |
cebix |
1.1 |
|
179 |
gbeauche |
1.11 |
// Find and set default gamma table |
180 |
|
|
csSave->gammaTable = 0; |
181 |
|
|
csSave->maxGammaTableSize = 0; |
182 |
cebix |
1.1 |
set_gamma(csSave, 0); |
183 |
|
|
|
184 |
|
|
// Install and activate interrupt service |
185 |
gbeauche |
1.4 |
SheepVar32 theServiceID = 0; |
186 |
gbeauche |
1.12 |
VSLNewInterruptService(csSave->regEntryID, FOURCC('v','b','l',' '), theServiceID.addr()); |
187 |
gbeauche |
1.4 |
csSave->vslServiceID = theServiceID.value(); |
188 |
cebix |
1.1 |
D(bug(" Interrupt ServiceID %08lx\n", csSave->vslServiceID)); |
189 |
|
|
csSave->interruptsEnabled = true; |
190 |
|
|
|
191 |
|
|
return noErr; |
192 |
|
|
} |
193 |
|
|
|
194 |
|
|
|
195 |
|
|
/* |
196 |
|
|
* Video driver control routine |
197 |
|
|
*/ |
198 |
|
|
|
199 |
gbeauche |
1.11 |
static bool allocate_gamma_table(VidLocals *csSave, uint32 size) |
200 |
|
|
{ |
201 |
|
|
if (size > csSave->maxGammaTableSize) { |
202 |
|
|
if (csSave->gammaTable) { |
203 |
|
|
Mac_sysfree(csSave->gammaTable); |
204 |
|
|
csSave->gammaTable = 0; |
205 |
|
|
csSave->maxGammaTableSize = 0; |
206 |
|
|
} |
207 |
|
|
if ((csSave->gammaTable = Mac_sysalloc(size)) == 0) |
208 |
|
|
return false; |
209 |
|
|
csSave->maxGammaTableSize = size; |
210 |
|
|
} |
211 |
|
|
return true; |
212 |
|
|
} |
213 |
|
|
|
214 |
cebix |
1.1 |
static int16 set_gamma(VidLocals *csSave, uint32 gamma) |
215 |
|
|
{ |
216 |
gbeauche |
1.11 |
return paramErr; |
217 |
|
|
|
218 |
|
|
if (gamma == 0) { // Build linear ramp, 256 entries |
219 |
|
|
|
220 |
|
|
// Allocate new table, if necessary |
221 |
|
|
if (!allocate_gamma_table(csSave, SIZEOF_GammaTbl + 256)) |
222 |
|
|
return memFullErr; |
223 |
|
|
|
224 |
|
|
// Initialize header |
225 |
|
|
WriteMacInt16(csSave->gammaTable + gVersion, 0); // A version 0 style of the GammaTbl structure |
226 |
|
|
WriteMacInt16(csSave->gammaTable + gType, 0); // Frame buffer hardware invariant |
227 |
|
|
WriteMacInt16(csSave->gammaTable + gFormulaSize, 0); // No formula data, just correction data |
228 |
|
|
WriteMacInt16(csSave->gammaTable + gChanCnt, 1); // Apply same correction to Red, Green, & Blue |
229 |
|
|
WriteMacInt16(csSave->gammaTable + gDataCnt, 256); // gDataCnt == 2^^gDataWidth |
230 |
|
|
WriteMacInt16(csSave->gammaTable + gDataWidth, 8); // 8 bits of significant data per entry |
231 |
cebix |
1.1 |
|
232 |
|
|
// Build the linear ramp |
233 |
gbeauche |
1.11 |
uint32 p = csSave->gammaTable + gFormulaData; |
234 |
|
|
for (int i=0; i<256; i++) |
235 |
|
|
WriteMacInt8(p + i, i); |
236 |
cebix |
1.1 |
|
237 |
gbeauche |
1.11 |
} else { // User-supplied gamma table |
238 |
cebix |
1.1 |
|
239 |
gbeauche |
1.11 |
// Validate header |
240 |
|
|
if (ReadMacInt16(gamma + gVersion) != 0) |
241 |
cebix |
1.1 |
return paramErr; |
242 |
gbeauche |
1.11 |
if (ReadMacInt16(gamma + gType) != 0) |
243 |
cebix |
1.1 |
return paramErr; |
244 |
gbeauche |
1.11 |
int chan_cnt = ReadMacInt16(gamma + gChanCnt); |
245 |
|
|
if (chan_cnt != 1 && chan_cnt != 3) |
246 |
cebix |
1.1 |
return paramErr; |
247 |
gbeauche |
1.11 |
int data_width = ReadMacInt16(gamma + gDataWidth); |
248 |
|
|
if (data_width > 8) |
249 |
cebix |
1.1 |
return paramErr; |
250 |
gbeauche |
1.11 |
int data_cnt = ReadMacInt16(gamma + gDataWidth); |
251 |
|
|
if (data_cnt != (1 << data_width)) |
252 |
cebix |
1.1 |
return paramErr; |
253 |
|
|
|
254 |
gbeauche |
1.11 |
// Allocate new table, if necessary |
255 |
|
|
int size = SIZEOF_GammaTbl + ReadMacInt16(gamma + gFormulaSize) + chan_cnt * data_cnt; |
256 |
|
|
if (!allocate_gamma_table(csSave, size)) |
257 |
|
|
return memFullErr; |
258 |
cebix |
1.1 |
|
259 |
gbeauche |
1.11 |
// Copy table |
260 |
|
|
Mac2Mac_memcpy(csSave->gammaTable, gamma, size); |
261 |
cebix |
1.1 |
} |
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 |
gbeauche |
1.11 |
if (csSave->gammaTable) { |
302 |
|
|
#ifdef __BEOS__ |
303 |
|
|
// Windows are gamma-corrected by BeOS |
304 |
|
|
const bool can_do_gamma = (display_type == DIS_SCREEN); |
305 |
|
|
#else |
306 |
|
|
const bool can_do_gamma = true; |
307 |
|
|
#endif |
308 |
|
|
if (can_do_gamma) { |
309 |
|
|
uint32 gamma_table = csSave->gammaTable; |
310 |
|
|
red_gamma = Mac2HostAddr(gamma_table + gFormulaData + ReadMacInt16(gamma_table + gFormulaSize)); |
311 |
|
|
int chan_cnt = ReadMacInt16(gamma_table + gChanCnt); |
312 |
|
|
if (chan_cnt == 1) |
313 |
|
|
green_gamma = blue_gamma = red_gamma; |
314 |
|
|
else { |
315 |
|
|
int ofs = ReadMacInt16(gamma_table + gDataCnt); |
316 |
|
|
green_gamma = red_gamma + ofs; |
317 |
|
|
blue_gamma = green_gamma + ofs; |
318 |
|
|
} |
319 |
|
|
gamma_data_width = ReadMacInt16(gamma_table + gDataWidth); |
320 |
|
|
do_gamma = true; |
321 |
cebix |
1.1 |
} |
322 |
|
|
} |
323 |
|
|
|
324 |
|
|
// Set palette |
325 |
|
|
rgb_color *d_pal; |
326 |
gbeauche |
1.6 |
if (start == 0xffff) { // Indexed |
327 |
cebix |
1.1 |
for (int i=0; i<=count; i++) { |
328 |
gbeauche |
1.6 |
d_pal = mac_pal + (ReadMacInt16(s_pal + csValue) & 0xff); |
329 |
|
|
uint8 red = (uint16)ReadMacInt16(s_pal + csRed) >> 8; |
330 |
|
|
uint8 green = (uint16)ReadMacInt16(s_pal + csGreen) >> 8; |
331 |
|
|
uint8 blue = (uint16)ReadMacInt16(s_pal + csBlue) >> 8; |
332 |
cebix |
1.1 |
if (csSave->luminanceMapping) |
333 |
|
|
red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16; |
334 |
|
|
if (do_gamma) { |
335 |
|
|
red = red_gamma[red >> (8 - gamma_data_width)]; |
336 |
|
|
green = green_gamma[green >> (8 - gamma_data_width)]; |
337 |
|
|
blue = blue_gamma[blue >> (8 - gamma_data_width)]; |
338 |
|
|
} |
339 |
|
|
(*d_pal).red = red; |
340 |
|
|
(*d_pal).green = green; |
341 |
|
|
(*d_pal).blue = blue; |
342 |
gbeauche |
1.6 |
s_pal += 8; |
343 |
cebix |
1.1 |
} |
344 |
gbeauche |
1.6 |
} else { // Sequential |
345 |
|
|
d_pal = mac_pal + start; |
346 |
cebix |
1.1 |
for (int i=0; i<=count; i++) { |
347 |
gbeauche |
1.6 |
uint8 red = (uint16)ReadMacInt16(s_pal + csRed) >> 8; |
348 |
|
|
uint8 green = (uint16)ReadMacInt16(s_pal + csGreen) >> 8; |
349 |
|
|
uint8 blue = (uint16)ReadMacInt16(s_pal + csBlue) >> 8; |
350 |
cebix |
1.1 |
if (csSave->luminanceMapping) |
351 |
|
|
red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16; |
352 |
|
|
if (do_gamma) { |
353 |
|
|
red = red_gamma[red >> (8 - gamma_data_width)]; |
354 |
|
|
green = green_gamma[green >> (8 - gamma_data_width)]; |
355 |
|
|
blue = blue_gamma[blue >> (8 - gamma_data_width)]; |
356 |
|
|
} |
357 |
|
|
(*d_pal).red = red; |
358 |
|
|
(*d_pal).green = green; |
359 |
|
|
(*d_pal).blue = blue; |
360 |
gbeauche |
1.6 |
d_pal++; |
361 |
|
|
s_pal += 8; |
362 |
cebix |
1.1 |
} |
363 |
|
|
} |
364 |
|
|
video_set_palette(); |
365 |
|
|
return noErr; |
366 |
|
|
} |
367 |
|
|
|
368 |
gbeauche |
1.11 |
case cscSetGamma: { // SetGamma |
369 |
|
|
uint32 user_table = ReadMacInt32(param + csGTable); |
370 |
|
|
D(bug("SetGamma %08x\n", user_table)); |
371 |
|
|
return set_gamma(csSave, ReadMacInt32(user_table)); |
372 |
|
|
} |
373 |
cebix |
1.1 |
|
374 |
|
|
case cscGrayPage: { // GrayPage |
375 |
gbeauche |
1.6 |
D(bug("GrayPage %d\n", ReadMacInt16(param + csPage))); |
376 |
|
|
if (ReadMacInt16(param + csPage)) |
377 |
|
|
return paramErr; |
378 |
|
|
|
379 |
|
|
uint32 pattern[6] = { |
380 |
|
|
0xaaaaaaaa, // 1 bpp |
381 |
|
|
0xcccccccc, // 2 bpp |
382 |
|
|
0xf0f0f0f0, // 4 bpp |
383 |
|
|
0xff00ff00, // 8 bpp |
384 |
|
|
0xffff0000, // 16 bpp |
385 |
|
|
0xffffffff // 32 bpp |
386 |
|
|
}; |
387 |
|
|
uint32 p = csSave->saveBaseAddr; |
388 |
|
|
uint32 pat = pattern[VModes[cur_mode].viAppleMode - APPLE_1_BIT]; |
389 |
|
|
bool invert = (VModes[cur_mode].viAppleMode == APPLE_32_BIT); |
390 |
|
|
for (uint32 y=0; y<VModes[cur_mode].viYsize; y++) { |
391 |
|
|
for (uint32 x=0; x<VModes[cur_mode].viRowBytes; x+=4) { |
392 |
|
|
WriteMacInt32(p + x, pat); |
393 |
|
|
if (invert) |
394 |
|
|
pat = ~pat; |
395 |
|
|
} |
396 |
|
|
p += VModes[cur_mode].viRowBytes; |
397 |
|
|
pat = ~pat; |
398 |
cebix |
1.1 |
} |
399 |
|
|
return noErr; |
400 |
|
|
} |
401 |
|
|
|
402 |
|
|
case cscSetGray: // SetGray |
403 |
|
|
D(bug("SetGray %02x\n", ReadMacInt8(param))); |
404 |
|
|
csSave->luminanceMapping = ReadMacInt8(param); |
405 |
|
|
return noErr; |
406 |
|
|
|
407 |
|
|
case cscSetInterrupt: // SetInterrupt |
408 |
|
|
D(bug("SetInterrupt\n")); |
409 |
|
|
csSave->interruptsEnabled = !ReadMacInt8(param); |
410 |
|
|
return noErr; |
411 |
|
|
|
412 |
|
|
case cscDirectSetEntries: // DirectSetEntries |
413 |
|
|
D(bug("DirectSetEntries\n")); |
414 |
|
|
return controlErr; |
415 |
|
|
|
416 |
|
|
case cscSetDefaultMode: // SetDefaultMode |
417 |
|
|
D(bug("SetDefaultMode\n")); |
418 |
|
|
return controlErr; |
419 |
|
|
|
420 |
|
|
case cscSwitchMode: |
421 |
|
|
D(bug("cscSwitchMode (Display Manager support) \nMode:%02x ID:%04x Page:%d\n", |
422 |
|
|
ReadMacInt16(param + csMode), ReadMacInt32(param + csData), ReadMacInt16(param + csPage))); |
423 |
|
|
return video_mode_change(csSave, param); |
424 |
|
|
|
425 |
|
|
case cscSavePreferredConfiguration: |
426 |
|
|
D(bug("SavePreferredConfiguration\n")); |
427 |
|
|
save_conf_id = ReadMacInt32(param + csData); |
428 |
|
|
save_conf_mode = ReadMacInt16(param + csMode); |
429 |
|
|
return noErr; |
430 |
|
|
|
431 |
|
|
case cscSetHardwareCursor: { |
432 |
|
|
// D(bug("SetHardwareCursor\n")); |
433 |
asvitkine |
1.16 |
|
434 |
|
|
if (!csSave->cursorHardware) |
435 |
|
|
return controlErr; |
436 |
|
|
|
437 |
cebix |
1.1 |
csSave->cursorSet = false; |
438 |
|
|
bool changed = false; |
439 |
|
|
|
440 |
|
|
// Image |
441 |
|
|
uint32 cursor = ReadMacInt32(param); // Pointer to CursorImage |
442 |
|
|
uint32 pmhandle = ReadMacInt32(cursor + ciCursorPixMap); |
443 |
|
|
if (pmhandle == 0 || ReadMacInt32(pmhandle) == 0) |
444 |
|
|
return controlErr; |
445 |
|
|
uint32 pixmap = ReadMacInt32(pmhandle); |
446 |
asvitkine |
1.16 |
|
447 |
|
|
// XXX: only certain image formats are handled properly at the moment |
448 |
|
|
uint16 rowBytes = ReadMacInt16(pixmap + 4) & 0x7FFF; |
449 |
|
|
if (rowBytes != 2) |
450 |
|
|
return controlErr; |
451 |
cebix |
1.1 |
|
452 |
|
|
// Mask |
453 |
|
|
uint32 bmhandle = ReadMacInt32(cursor + ciCursorBitMask); |
454 |
|
|
if (bmhandle == 0 || ReadMacInt32(bmhandle) == 0) |
455 |
|
|
return controlErr; |
456 |
|
|
uint32 bitmap = ReadMacInt32(bmhandle); |
457 |
asvitkine |
1.16 |
|
458 |
|
|
// Get cursor data even on a screen, to set the right cursor image when switching back to a window. |
459 |
|
|
// Hotspot is stale, but will be fixed by the next call to DrawHardwareCursor, which is likely to |
460 |
|
|
// occur immediately hereafter. |
461 |
|
|
|
462 |
|
|
if (memcmp(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32)) { |
463 |
|
|
memcpy(MacCursor + 4, Mac2HostAddr(ReadMacInt32(pixmap)), 32); |
464 |
|
|
changed = true; |
465 |
|
|
} |
466 |
cebix |
1.1 |
if (memcmp(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32)) { |
467 |
|
|
memcpy(MacCursor + 4 + 32, Mac2HostAddr(ReadMacInt32(bitmap)), 32); |
468 |
|
|
changed = true; |
469 |
|
|
} |
470 |
|
|
|
471 |
|
|
// Set new cursor image |
472 |
gbeauche |
1.8 |
if (!video_can_change_cursor()) |
473 |
cebix |
1.1 |
return controlErr; |
474 |
|
|
if (changed) |
475 |
|
|
video_set_cursor(); |
476 |
|
|
|
477 |
|
|
csSave->cursorSet = true; |
478 |
asvitkine |
1.16 |
csSave->cursorHotFlag = true; |
479 |
cebix |
1.1 |
return noErr; |
480 |
|
|
} |
481 |
|
|
|
482 |
asvitkine |
1.16 |
case cscDrawHardwareCursor: { |
483 |
cebix |
1.1 |
// D(bug("DrawHardwareCursor\n")); |
484 |
asvitkine |
1.16 |
|
485 |
|
|
if (!csSave->cursorHardware) |
486 |
|
|
return controlErr; |
487 |
|
|
|
488 |
|
|
int32 oldX = csSave->cursorX; |
489 |
|
|
int32 oldY = csSave->cursorY; |
490 |
|
|
uint32 oldVisible = csSave->cursorVisible; |
491 |
|
|
|
492 |
cebix |
1.1 |
csSave->cursorX = ReadMacInt32(param + csCursorX); |
493 |
|
|
csSave->cursorY = ReadMacInt32(param + csCursorY); |
494 |
|
|
csSave->cursorVisible = ReadMacInt32(param + csCursorVisible); |
495 |
asvitkine |
1.16 |
bool changed = (csSave->cursorVisible != oldVisible); |
496 |
|
|
|
497 |
|
|
// If this is the first DrawHardwareCursor call since the cursor was last set (via SetHardwareCursor), |
498 |
|
|
// attempt to set an appropriate cursor hotspot. SetHardwareCursor itself does not know what the |
499 |
|
|
// hotspot should be; it knows only the cursor image and mask. The hotspot is known only to the caller, |
500 |
|
|
// and we have to try to infer it here. The usual sequence of calls when changing the cursor is: |
501 |
|
|
// |
502 |
|
|
// DrawHardwareCursor with (oldX, oldY, invisible) |
503 |
|
|
// SetHardwareCursor with (cursor) |
504 |
|
|
// DrawHardwareCursor with (newX, newY, visible) |
505 |
|
|
// |
506 |
|
|
// The key thing to note is that the sequence is intended not to change the current screen pixel location |
507 |
|
|
// indicated by the hotspot. Thus, the difference between (newX, newY) and (oldX, oldY) reflects precisely |
508 |
|
|
// the difference between the old cursor hotspot and the new one. For example, if you change from a |
509 |
|
|
// cursor whose hotspot is (1, 1) to one whose hotspot is (7, 4), then you must adjust the cursor position |
510 |
|
|
// by (-6, -3) in order for the same screen pixel to remain under the new hotspot. |
511 |
|
|
// |
512 |
|
|
// Alas, on rare occasions this heuristic can fail, and if you did nothing else you could even get stuck |
513 |
|
|
// with the wrong hotspot from then on. To address that possibility, we force the hotspot to (1, 1) |
514 |
|
|
// whenever the cursor being drawn is the standard arrow. Thus, while it is very unlikely that you will |
515 |
|
|
// ever have the wrong hotspot, if you do, it is easy to recover. |
516 |
|
|
|
517 |
|
|
if (csSave->cursorHotFlag) { |
518 |
|
|
csSave->cursorHotFlag = false; |
519 |
|
|
D(bug("old hotspot (%d, %d)\n", csSave->cursorHotX, csSave->cursorHotY)); |
520 |
|
|
|
521 |
|
|
static uint8 arrow[] = { |
522 |
|
|
0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, 0x78, 0x00, 0x7C, 0x00, 0x7E, 0x00, 0x7F, 0x00, |
523 |
|
|
0x7F, 0x80, 0x7C, 0x00, 0x6C, 0x00, 0x46, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, |
524 |
|
|
}; |
525 |
|
|
if (memcmp(MacCursor + 4, arrow, 32) == 0) { |
526 |
|
|
csSave->cursorHotX = 1; |
527 |
|
|
csSave->cursorHotY = 1; |
528 |
|
|
} else if (csSave->cursorX != oldX || csSave->cursorY != oldY) { |
529 |
|
|
int32 hotX = csSave->cursorHotX + (oldX - csSave->cursorX); |
530 |
|
|
int32 hotY = csSave->cursorHotY + (oldY - csSave->cursorY); |
531 |
|
|
|
532 |
|
|
if (0 <= hotX && hotX <= 15 && 0 <= hotY && hotY <= 15) { |
533 |
|
|
csSave->cursorHotX = hotX; |
534 |
|
|
csSave->cursorHotY = hotY; |
535 |
|
|
} |
536 |
|
|
} |
537 |
|
|
if (MacCursor[2] != csSave->cursorHotX || MacCursor[3] != csSave->cursorHotY) { |
538 |
|
|
MacCursor[2] = csSave->cursorHotX; |
539 |
|
|
MacCursor[3] = csSave->cursorHotY; |
540 |
|
|
changed = true; |
541 |
|
|
} |
542 |
|
|
D(bug("new hotspot (%d, %d)\n", csSave->cursorHotX, csSave->cursorHotY)); |
543 |
|
|
} |
544 |
|
|
|
545 |
|
|
if (changed && video_can_change_cursor()) |
546 |
|
|
video_set_cursor(); |
547 |
|
|
|
548 |
cebix |
1.1 |
return noErr; |
549 |
asvitkine |
1.16 |
} |
550 |
cebix |
1.1 |
|
551 |
|
|
case 43: { // Driver Gestalt |
552 |
|
|
uint32 sel = ReadMacInt32(pb + csParam); |
553 |
|
|
D(bug(" driver gestalt %c%c%c%c\n", sel >> 24, sel >> 16, sel >> 8, sel)); |
554 |
|
|
switch (sel) { |
555 |
|
|
case FOURCC('v','e','r','s'): |
556 |
|
|
WriteMacInt32(pb + csParam + 4, 0x01008000); |
557 |
|
|
break; |
558 |
|
|
case FOURCC('i','n','t','f'): |
559 |
|
|
WriteMacInt32(pb + csParam + 4, FOURCC('c','a','r','d')); |
560 |
|
|
break; |
561 |
|
|
case FOURCC('s','y','n','c'): |
562 |
|
|
WriteMacInt32(pb + csParam + 4, 0x01000000); |
563 |
|
|
break; |
564 |
|
|
default: |
565 |
|
|
return statusErr; |
566 |
|
|
}; |
567 |
|
|
return noErr; |
568 |
|
|
} |
569 |
|
|
|
570 |
|
|
default: |
571 |
|
|
D(bug(" unknown control code %d\n", code)); |
572 |
|
|
return controlErr; |
573 |
|
|
} |
574 |
|
|
} |
575 |
|
|
|
576 |
|
|
|
577 |
|
|
/* |
578 |
|
|
* Video driver status routine |
579 |
|
|
*/ |
580 |
|
|
|
581 |
|
|
// Search for given AppleID in mode table |
582 |
|
|
static bool has_mode(uint32 id) |
583 |
|
|
{ |
584 |
|
|
VideoInfo *p = VModes; |
585 |
|
|
while (p->viType != DIS_INVALID) { |
586 |
|
|
if (p->viAppleID == id) |
587 |
|
|
return true; |
588 |
|
|
p++; |
589 |
|
|
} |
590 |
|
|
return false; |
591 |
|
|
} |
592 |
|
|
|
593 |
|
|
// Find maximum depth for given AppleID |
594 |
|
|
static uint32 max_depth(uint32 id) |
595 |
|
|
{ |
596 |
|
|
uint32 max = APPLE_1_BIT; |
597 |
|
|
VideoInfo *p = VModes; |
598 |
|
|
while (p->viType != DIS_INVALID) { |
599 |
|
|
if (p->viAppleID == id && p->viAppleMode > max) |
600 |
|
|
max = p->viAppleMode; |
601 |
|
|
p++; |
602 |
|
|
} |
603 |
|
|
return max; |
604 |
|
|
} |
605 |
|
|
|
606 |
gbeauche |
1.14 |
// Get X/Y size of specified resolution |
607 |
|
|
static void get_size_of_resolution(int id, uint32 &x, uint32 &y) |
608 |
|
|
{ |
609 |
|
|
VideoInfo *p = VModes; |
610 |
|
|
while (p->viType != DIS_INVALID) { |
611 |
|
|
if (p->viAppleID == id) { |
612 |
|
|
x = p->viXsize; |
613 |
|
|
y = p->viYsize; |
614 |
|
|
return; |
615 |
|
|
} |
616 |
|
|
p++; |
617 |
|
|
} |
618 |
|
|
x = y = 0; |
619 |
|
|
} |
620 |
|
|
|
621 |
cebix |
1.1 |
static int16 VideoStatus(uint32 pb, VidLocals *csSave) |
622 |
|
|
{ |
623 |
|
|
int16 code = ReadMacInt16(pb + csCode); |
624 |
|
|
D(bug("VideoStatus %d: ", code)); |
625 |
|
|
uint32 param = ReadMacInt32(pb + csParam); |
626 |
|
|
switch (code) { |
627 |
|
|
|
628 |
|
|
case cscGetMode: // GetMode |
629 |
|
|
D(bug("GetMode\n")); |
630 |
|
|
WriteMacInt32(param + csBaseAddr, csSave->saveBaseAddr); |
631 |
|
|
WriteMacInt16(param + csMode, csSave->saveMode); |
632 |
|
|
WriteMacInt16(param + csPage, csSave->savePage); |
633 |
|
|
D(bug("return: mode:%04x page:%04x ", ReadMacInt16(param + csMode), |
634 |
|
|
ReadMacInt16(param + csPage))); |
635 |
|
|
D(bug("base adress %08lx\n", ReadMacInt32(param + csBaseAddr))); |
636 |
|
|
return noErr; |
637 |
|
|
|
638 |
|
|
case cscGetEntries: { // GetEntries |
639 |
|
|
D(bug("GetEntries\n")); |
640 |
gbeauche |
1.6 |
uint32 d_pal = ReadMacInt32(param + csTable); |
641 |
|
|
uint16 start = ReadMacInt16(param + csStart); |
642 |
|
|
uint16 count = ReadMacInt16(param + csCount); |
643 |
cebix |
1.1 |
rgb_color *s_pal; |
644 |
|
|
if ((VModes[cur_mode].viAppleMode == APPLE_32_BIT)|| |
645 |
|
|
(VModes[cur_mode].viAppleMode == APPLE_16_BIT)) { |
646 |
|
|
D(bug("ERROR: GetEntries in direct mode \n")); |
647 |
|
|
return statusErr; |
648 |
|
|
} |
649 |
gbeauche |
1.6 |
|
650 |
|
|
if (start == 0xffff) { // Indexed |
651 |
cebix |
1.1 |
for (uint16 i=0;i<count;i++) { |
652 |
gbeauche |
1.6 |
s_pal = mac_pal + (ReadMacInt16(d_pal + csValue) & 0xff); |
653 |
|
|
uint8 red = (*s_pal).red; |
654 |
|
|
uint8 green = (*s_pal).green; |
655 |
|
|
uint8 blue = (*s_pal).blue; |
656 |
|
|
WriteMacInt16(d_pal + csRed, red * 0x0101); |
657 |
|
|
WriteMacInt16(d_pal + csGreen, green * 0x0101); |
658 |
|
|
WriteMacInt16(d_pal + csBlue, blue * 0x0101); |
659 |
|
|
d_pal += 8; |
660 |
cebix |
1.1 |
} |
661 |
gbeauche |
1.6 |
} else { // Sequential |
662 |
|
|
if (start + count > 255) |
663 |
|
|
return paramErr; |
664 |
|
|
s_pal = mac_pal + start; |
665 |
cebix |
1.1 |
for (uint16 i=0;i<count;i++) { |
666 |
gbeauche |
1.6 |
uint8 red = (*s_pal).red; |
667 |
|
|
uint8 green = (*s_pal).green; |
668 |
|
|
uint8 blue = (*s_pal).blue; |
669 |
|
|
s_pal++; |
670 |
|
|
WriteMacInt16(d_pal + csRed, red * 0x0101); |
671 |
|
|
WriteMacInt16(d_pal + csGreen, green * 0x0101); |
672 |
|
|
WriteMacInt16(d_pal + csBlue, blue * 0x0101); |
673 |
|
|
d_pal += 8; |
674 |
cebix |
1.1 |
} |
675 |
|
|
}; |
676 |
|
|
return noErr; |
677 |
|
|
} |
678 |
|
|
|
679 |
|
|
case cscGetPageCnt: // GetPage |
680 |
|
|
D(bug("GetPage\n")); |
681 |
|
|
WriteMacInt16(param + csPage, 1); |
682 |
|
|
return noErr; |
683 |
|
|
|
684 |
|
|
case cscGetPageBase: // GetPageBase |
685 |
|
|
D(bug("GetPageBase\n")); |
686 |
|
|
WriteMacInt32(param + csBaseAddr, csSave->saveBaseAddr); |
687 |
|
|
return noErr; |
688 |
|
|
|
689 |
|
|
case cscGetGray: // GetGray |
690 |
|
|
D(bug("GetGray\n")); |
691 |
|
|
WriteMacInt8(param, csSave->luminanceMapping ? 1 : 0); |
692 |
|
|
return noErr; |
693 |
|
|
|
694 |
|
|
case cscGetInterrupt: // GetInterrupt |
695 |
|
|
D(bug("GetInterrupt\n")); |
696 |
|
|
WriteMacInt8(param, csSave->interruptsEnabled ? 0 : 1); |
697 |
|
|
return noErr; |
698 |
|
|
|
699 |
|
|
case cscGetGamma: // GetGamma |
700 |
|
|
D(bug("GetGamma\n")); |
701 |
|
|
WriteMacInt32(param, (uint32)csSave->gammaTable); |
702 |
|
|
return statusErr; |
703 |
|
|
|
704 |
|
|
case cscGetDefaultMode: // GetDefaultMode |
705 |
|
|
D(bug("GetDefaultMode\n")); |
706 |
|
|
return statusErr; |
707 |
|
|
|
708 |
|
|
case cscGetCurMode: // GetCurMode |
709 |
|
|
D(bug("GetCurMode\n")); |
710 |
|
|
WriteMacInt16(param + csMode, csSave->saveMode); |
711 |
|
|
WriteMacInt32(param + csData, csSave->saveData); |
712 |
|
|
WriteMacInt16(param + csPage, csSave->savePage); |
713 |
|
|
WriteMacInt32(param + csBaseAddr, csSave->saveBaseAddr); |
714 |
|
|
|
715 |
|
|
D(bug("return: mode:%04x ID:%08lx page:%04x ", ReadMacInt16(param + csMode), |
716 |
|
|
ReadMacInt32(param + csData), ReadMacInt16(param + csPage))); |
717 |
|
|
D(bug("base adress %08lx\n", ReadMacInt32(param + csBaseAddr))); |
718 |
|
|
return noErr; |
719 |
|
|
|
720 |
|
|
case cscGetConnection: // GetConnection |
721 |
|
|
D(bug("GetConnection\n")); |
722 |
|
|
WriteMacInt16(param + csDisplayType, kMultiModeCRT3Connect); |
723 |
|
|
WriteMacInt8(param + csConnectTaggedType, 6); |
724 |
|
|
WriteMacInt8(param + csConnectTaggedData, 0x23); |
725 |
|
|
WriteMacInt32(param + csConnectFlags, (1<<kAllModesValid)|(1<<kAllModesSafe)); |
726 |
|
|
WriteMacInt32(param + csDisplayComponent, 0); |
727 |
|
|
return noErr; |
728 |
|
|
|
729 |
|
|
case cscGetModeBaseAddress: |
730 |
|
|
D(bug("GetModeBaseAddress (obsolete !) \n")); |
731 |
|
|
return statusErr; |
732 |
|
|
|
733 |
|
|
case cscGetPreferredConfiguration: |
734 |
|
|
D(bug("GetPreferredConfiguration \n")); |
735 |
|
|
WriteMacInt16(param + csMode, save_conf_mode); |
736 |
|
|
WriteMacInt32(param + csData, save_conf_id); |
737 |
|
|
return noErr; |
738 |
|
|
|
739 |
|
|
case cscGetNextResolution: { |
740 |
|
|
D(bug("GetNextResolution \n")); |
741 |
|
|
int work_id = ReadMacInt32(param + csPreviousDisplayModeID); |
742 |
|
|
switch (work_id) { |
743 |
|
|
case kDisplayModeIDCurrent: |
744 |
|
|
work_id = csSave->saveData; |
745 |
|
|
break; |
746 |
|
|
case kDisplayModeIDFindFirstResolution: |
747 |
|
|
work_id = APPLE_ID_MIN; |
748 |
|
|
while (!has_mode(work_id)) |
749 |
|
|
work_id ++; |
750 |
|
|
break; |
751 |
|
|
default: |
752 |
|
|
if (!has_mode(work_id)) |
753 |
|
|
return paramErr; |
754 |
|
|
work_id++; |
755 |
|
|
while (!has_mode(work_id)) { |
756 |
|
|
work_id++; |
757 |
|
|
if (work_id > APPLE_ID_MAX) { |
758 |
|
|
WriteMacInt32(param + csRIDisplayModeID, kDisplayModeIDNoMoreResolutions); |
759 |
|
|
return noErr; |
760 |
|
|
} |
761 |
|
|
} |
762 |
|
|
break; |
763 |
|
|
} |
764 |
|
|
WriteMacInt32(param + csRIDisplayModeID, work_id); |
765 |
|
|
WriteMacInt16(param + csMaxDepthMode, max_depth(work_id)); |
766 |
|
|
switch (work_id) { |
767 |
|
|
case APPLE_640x480: |
768 |
|
|
WriteMacInt32(param + csHorizontalPixels, 640); |
769 |
|
|
WriteMacInt32(param + csVerticalLines, 480); |
770 |
|
|
WriteMacInt32(param + csRefreshRate, 75<<16); |
771 |
|
|
break; |
772 |
|
|
case APPLE_W_640x480: |
773 |
|
|
WriteMacInt32(param + csHorizontalPixels, 640); |
774 |
|
|
WriteMacInt32(param + csVerticalLines, 480); |
775 |
|
|
WriteMacInt32(param + csRefreshRate, 60<<16); |
776 |
|
|
break; |
777 |
|
|
case APPLE_800x600: |
778 |
|
|
WriteMacInt32(param + csHorizontalPixels, 800); |
779 |
|
|
WriteMacInt32(param + csVerticalLines, 600); |
780 |
|
|
WriteMacInt32(param + csRefreshRate, 75<<16); |
781 |
|
|
break; |
782 |
|
|
case APPLE_W_800x600: |
783 |
|
|
WriteMacInt32(param + csHorizontalPixels, 800); |
784 |
|
|
WriteMacInt32(param + csVerticalLines, 600); |
785 |
|
|
WriteMacInt32(param + csRefreshRate, 60<<16); |
786 |
|
|
break; |
787 |
|
|
case APPLE_1024x768: |
788 |
|
|
WriteMacInt32(param + csHorizontalPixels, 1024); |
789 |
|
|
WriteMacInt32(param + csVerticalLines, 768); |
790 |
|
|
WriteMacInt32(param + csRefreshRate, 75<<16); |
791 |
|
|
break; |
792 |
gbeauche |
1.7 |
case APPLE_1152x768: |
793 |
|
|
WriteMacInt32(param + csHorizontalPixels, 1152); |
794 |
|
|
WriteMacInt32(param + csVerticalLines, 768); |
795 |
|
|
WriteMacInt32(param + csRefreshRate, 75<<16); |
796 |
|
|
break; |
797 |
cebix |
1.1 |
case APPLE_1152x900: |
798 |
|
|
WriteMacInt32(param + csHorizontalPixels, 1152); |
799 |
|
|
WriteMacInt32(param + csVerticalLines, 900); |
800 |
|
|
WriteMacInt32(param + csRefreshRate, 75<<16); |
801 |
|
|
break; |
802 |
|
|
case APPLE_1280x1024: |
803 |
|
|
WriteMacInt32(param + csHorizontalPixels, 1280); |
804 |
|
|
WriteMacInt32(param + csVerticalLines, 1024); |
805 |
|
|
WriteMacInt32(param + csRefreshRate, 75<<16); |
806 |
|
|
break; |
807 |
|
|
case APPLE_1600x1200: |
808 |
|
|
WriteMacInt32(param + csHorizontalPixels, 1600); |
809 |
|
|
WriteMacInt32(param + csVerticalLines, 1200); |
810 |
|
|
WriteMacInt32(param + csRefreshRate, 75<<16); |
811 |
|
|
break; |
812 |
gbeauche |
1.14 |
case APPLE_CUSTOM: { |
813 |
|
|
uint32 x, y; |
814 |
|
|
get_size_of_resolution(work_id, x, y); |
815 |
|
|
WriteMacInt32(param + csHorizontalPixels, x); |
816 |
|
|
WriteMacInt32(param + csVerticalLines, y); |
817 |
|
|
WriteMacInt32(param + csRefreshRate, 75<<16); |
818 |
|
|
break; |
819 |
|
|
} |
820 |
cebix |
1.1 |
} |
821 |
|
|
return noErr; |
822 |
|
|
} |
823 |
|
|
|
824 |
|
|
case cscGetVideoParameters: // GetVideoParameters |
825 |
|
|
D(bug("GetVideoParameters ID:%08lx Depth:%04x\n", |
826 |
|
|
ReadMacInt32(param + csDisplayModeID), |
827 |
|
|
ReadMacInt16(param + csDepthMode))); |
828 |
|
|
|
829 |
|
|
// find right video mode |
830 |
|
|
for (int i=0; VModes[i].viType!=DIS_INVALID; i++) { |
831 |
|
|
if ((ReadMacInt16(param + csDepthMode) == VModes[i].viAppleMode) && |
832 |
|
|
(ReadMacInt32(param + csDisplayModeID) == VModes[i].viAppleID)) { |
833 |
|
|
uint32 vpb = ReadMacInt32(param + csVPBlockPtr); |
834 |
|
|
WriteMacInt32(vpb + vpBaseOffset, 0); |
835 |
|
|
WriteMacInt16(vpb + vpRowBytes, VModes[i].viRowBytes); |
836 |
|
|
WriteMacInt16(vpb + vpBounds, 0); |
837 |
|
|
WriteMacInt16(vpb + vpBounds + 2, 0); |
838 |
|
|
WriteMacInt16(vpb + vpBounds + 4, VModes[i].viYsize); |
839 |
|
|
WriteMacInt16(vpb + vpBounds + 6, VModes[i].viXsize); |
840 |
|
|
WriteMacInt16(vpb + vpVersion, 0); // Pixel Map version number |
841 |
|
|
WriteMacInt16(vpb + vpPackType, 0); |
842 |
|
|
WriteMacInt32(vpb + vpPackSize, 0); |
843 |
|
|
WriteMacInt32(vpb + vpHRes, 0x00480000); // horiz res of the device (ppi) |
844 |
|
|
WriteMacInt32(vpb + vpVRes, 0x00480000); // vert res of the device (ppi) |
845 |
|
|
switch (VModes[i].viAppleMode) { |
846 |
|
|
case APPLE_1_BIT: |
847 |
|
|
WriteMacInt16(vpb + vpPixelType, 0); |
848 |
|
|
WriteMacInt16(vpb + vpPixelSize, 1); |
849 |
|
|
WriteMacInt16(vpb + vpCmpCount, 1); |
850 |
|
|
WriteMacInt16(vpb + vpCmpSize, 1); |
851 |
|
|
WriteMacInt32(param + csDeviceType, 0); // CLUT |
852 |
|
|
break; |
853 |
|
|
case APPLE_2_BIT: |
854 |
|
|
WriteMacInt16(vpb + vpPixelType, 0); |
855 |
|
|
WriteMacInt16(vpb + vpPixelSize, 2); |
856 |
|
|
WriteMacInt16(vpb + vpCmpCount, 1); |
857 |
|
|
WriteMacInt16(vpb + vpCmpSize, 2); |
858 |
|
|
WriteMacInt32(param + csDeviceType, 0); // CLUT |
859 |
|
|
break; |
860 |
|
|
case APPLE_4_BIT: |
861 |
|
|
WriteMacInt16(vpb + vpPixelType, 0); |
862 |
|
|
WriteMacInt16(vpb + vpPixelSize, 4); |
863 |
|
|
WriteMacInt16(vpb + vpCmpCount, 1); |
864 |
|
|
WriteMacInt16(vpb + vpCmpSize, 4); |
865 |
|
|
WriteMacInt32(param + csDeviceType, 0); // CLUT |
866 |
|
|
break; |
867 |
|
|
case APPLE_8_BIT: |
868 |
|
|
WriteMacInt16(vpb + vpPixelType, 0); |
869 |
|
|
WriteMacInt16(vpb + vpPixelSize, 8); |
870 |
|
|
WriteMacInt16(vpb + vpCmpCount, 1); |
871 |
|
|
WriteMacInt16(vpb + vpCmpSize, 8); |
872 |
|
|
WriteMacInt32(param + csDeviceType, 0); // CLUT |
873 |
|
|
break; |
874 |
|
|
case APPLE_16_BIT: |
875 |
|
|
WriteMacInt16(vpb + vpPixelType, 0x10); |
876 |
|
|
WriteMacInt16(vpb + vpPixelSize, 16); |
877 |
|
|
WriteMacInt16(vpb + vpCmpCount, 3); |
878 |
|
|
WriteMacInt16(vpb + vpCmpSize, 5); |
879 |
|
|
WriteMacInt32(param + csDeviceType, 2); // DIRECT |
880 |
|
|
break; |
881 |
|
|
case APPLE_32_BIT: |
882 |
|
|
WriteMacInt16(vpb + vpPixelType, 0x10); |
883 |
|
|
WriteMacInt16(vpb + vpPixelSize, 32); |
884 |
|
|
WriteMacInt16(vpb + vpCmpCount, 3); |
885 |
|
|
WriteMacInt16(vpb + vpCmpSize, 8); |
886 |
|
|
WriteMacInt32(param + csDeviceType, 2); // DIRECT |
887 |
|
|
break; |
888 |
|
|
} |
889 |
|
|
WriteMacInt32(param + csPageCount, 1); |
890 |
|
|
return noErr; |
891 |
|
|
} |
892 |
|
|
} |
893 |
|
|
return paramErr; |
894 |
|
|
|
895 |
|
|
case cscGetModeTiming: |
896 |
|
|
D(bug("GetModeTiming mode %08lx\n", ReadMacInt32(param + csTimingMode))); |
897 |
|
|
WriteMacInt32(param + csTimingFormat, kDeclROMtables); |
898 |
|
|
WriteMacInt32(param + csTimingFlags, (1<<kModeValid)|(1<<kModeSafe)|(1<<kShowModeNow)); // Mode valid, safe, default and shown in Monitors panel |
899 |
|
|
for (int i=0; VModes[i].viType!=DIS_INVALID; i++) { |
900 |
|
|
if (ReadMacInt32(param + csTimingMode) == VModes[i].viAppleID) { |
901 |
|
|
uint32 timing = timingUnknown; |
902 |
|
|
uint32 flags = (1<<kModeValid) | (1<<kShowModeNow); |
903 |
|
|
switch (VModes[i].viAppleID) { |
904 |
|
|
case APPLE_640x480: |
905 |
|
|
timing = timingVESA_640x480_75hz; |
906 |
|
|
flags |= (1<<kModeSafe); |
907 |
|
|
break; |
908 |
|
|
case APPLE_W_640x480: |
909 |
|
|
timing = timingVESA_640x480_60hz; |
910 |
|
|
flags |= (1<<kModeSafe); |
911 |
|
|
break; |
912 |
|
|
case APPLE_800x600: |
913 |
|
|
timing = timingVESA_800x600_75hz; |
914 |
|
|
flags |= (1<<kModeSafe); |
915 |
|
|
break; |
916 |
|
|
case APPLE_W_800x600: |
917 |
|
|
timing = timingVESA_800x600_60hz; |
918 |
|
|
flags |= (1<<kModeSafe); |
919 |
|
|
break; |
920 |
|
|
case APPLE_1024x768: |
921 |
|
|
timing = timingVESA_1024x768_75hz; |
922 |
gbeauche |
1.7 |
break; |
923 |
|
|
case APPLE_1152x768: |
924 |
|
|
timing = timingApple_1152x870_75hz; // FIXME |
925 |
cebix |
1.1 |
break; |
926 |
|
|
case APPLE_1152x900: |
927 |
|
|
timing = timingApple_1152x870_75hz; |
928 |
|
|
break; |
929 |
|
|
case APPLE_1280x1024: |
930 |
|
|
timing = timingVESA_1280x960_75hz; |
931 |
|
|
break; |
932 |
|
|
case APPLE_1600x1200: |
933 |
|
|
timing = timingVESA_1600x1200_75hz; |
934 |
|
|
break; |
935 |
|
|
default: |
936 |
|
|
timing = timingUnknown; |
937 |
|
|
break; |
938 |
|
|
} |
939 |
|
|
WriteMacInt32(param + csTimingData, timing); |
940 |
|
|
WriteMacInt32(param + csTimingFlags, flags); |
941 |
|
|
return noErr; |
942 |
|
|
} |
943 |
|
|
} |
944 |
|
|
return paramErr; |
945 |
|
|
|
946 |
|
|
case cscSupportsHardwareCursor: |
947 |
|
|
D(bug("SupportsHardwareCursor\n")); |
948 |
asvitkine |
1.16 |
WriteMacInt32(param, csSave->cursorHardware); |
949 |
cebix |
1.1 |
return noErr; |
950 |
|
|
|
951 |
|
|
case cscGetHardwareCursorDrawState: |
952 |
|
|
D(bug("GetHardwareCursorDrawState\n")); |
953 |
asvitkine |
1.16 |
|
954 |
|
|
if (!csSave->cursorHardware) |
955 |
|
|
return statusErr; |
956 |
|
|
|
957 |
cebix |
1.1 |
WriteMacInt32(param + csCursorX, csSave->cursorX); |
958 |
|
|
WriteMacInt32(param + csCursorY, csSave->cursorY); |
959 |
|
|
WriteMacInt32(param + csCursorVisible, csSave->cursorVisible); |
960 |
|
|
WriteMacInt32(param + csCursorSet, csSave->cursorSet); |
961 |
|
|
return noErr; |
962 |
|
|
|
963 |
|
|
default: |
964 |
|
|
D(bug(" unknown status code %d\n", code)); |
965 |
|
|
return statusErr; |
966 |
|
|
} |
967 |
|
|
} |
968 |
|
|
|
969 |
|
|
|
970 |
|
|
/* |
971 |
|
|
* Video driver close routine |
972 |
|
|
*/ |
973 |
|
|
|
974 |
|
|
static int16 VideoClose(uint32 pb, VidLocals *csSave) |
975 |
|
|
{ |
976 |
|
|
D(bug("VideoClose\n")); |
977 |
|
|
|
978 |
|
|
// Delete interrupt service |
979 |
|
|
csSave->interruptsEnabled = false; |
980 |
|
|
VSLDisposeInterruptService(csSave->vslServiceID); |
981 |
|
|
|
982 |
|
|
return noErr; |
983 |
|
|
} |
984 |
|
|
|
985 |
|
|
|
986 |
|
|
/* |
987 |
|
|
* Native (PCI) driver entry |
988 |
|
|
*/ |
989 |
|
|
|
990 |
gbeauche |
1.9 |
int16 VideoDoDriverIO(uint32 spaceID, uint32 commandID, uint32 commandContents, uint32 commandCode, uint32 commandKind) |
991 |
cebix |
1.1 |
{ |
992 |
gbeauche |
1.9 |
// D(bug("VideoDoDriverIO space %08x, command %08x, contents %08x, code %d, kind %d\n", spaceID, commandID, commandContents, commandCode, commandKind)); |
993 |
cebix |
1.1 |
int16 err = noErr; |
994 |
|
|
|
995 |
|
|
switch (commandCode) { |
996 |
|
|
case kInitializeCommand: |
997 |
|
|
case kReplaceCommand: |
998 |
gbeauche |
1.11 |
if (private_data != NULL) { // Might be left over from a reboot |
999 |
|
|
if (private_data->gammaTable) |
1000 |
|
|
Mac_sysfree(private_data->gammaTable); |
1001 |
gbeauche |
1.12 |
if (private_data->regEntryID) |
1002 |
|
|
Mac_sysfree(private_data->regEntryID); |
1003 |
gbeauche |
1.11 |
} |
1004 |
cebix |
1.1 |
delete private_data; |
1005 |
|
|
|
1006 |
gbeauche |
1.10 |
iocic_tvect = FindLibSymbol("\021DriverServicesLib", "\023IOCommandIsComplete"); |
1007 |
cebix |
1.1 |
D(bug("IOCommandIsComplete TVECT at %08lx\n", iocic_tvect)); |
1008 |
|
|
if (iocic_tvect == 0) { |
1009 |
|
|
printf("FATAL: VideoDoDriverIO(): Can't find IOCommandIsComplete()\n"); |
1010 |
|
|
err = -1; |
1011 |
|
|
break; |
1012 |
|
|
} |
1013 |
gbeauche |
1.10 |
vslnewis_tvect = FindLibSymbol("\020VideoServicesLib", "\026VSLNewInterruptService"); |
1014 |
cebix |
1.1 |
D(bug("VSLNewInterruptService TVECT at %08lx\n", vslnewis_tvect)); |
1015 |
|
|
if (vslnewis_tvect == 0) { |
1016 |
|
|
printf("FATAL: VideoDoDriverIO(): Can't find VSLNewInterruptService()\n"); |
1017 |
|
|
err = -1; |
1018 |
|
|
break; |
1019 |
|
|
} |
1020 |
gbeauche |
1.10 |
vsldisposeis_tvect = FindLibSymbol("\020VideoServicesLib", "\032VSLDisposeInterruptService"); |
1021 |
cebix |
1.1 |
D(bug("VSLDisposeInterruptService TVECT at %08lx\n", vsldisposeis_tvect)); |
1022 |
|
|
if (vsldisposeis_tvect == 0) { |
1023 |
|
|
printf("FATAL: VideoDoDriverIO(): Can't find VSLDisposeInterruptService()\n"); |
1024 |
|
|
err = -1; |
1025 |
|
|
break; |
1026 |
|
|
} |
1027 |
gbeauche |
1.10 |
vsldois_tvect = FindLibSymbol("\020VideoServicesLib", "\025VSLDoInterruptService"); |
1028 |
cebix |
1.1 |
D(bug("VSLDoInterruptService TVECT at %08lx\n", vsldois_tvect)); |
1029 |
|
|
if (vsldois_tvect == 0) { |
1030 |
|
|
printf("FATAL: VideoDoDriverIO(): Can't find VSLDoInterruptService()\n"); |
1031 |
|
|
err = -1; |
1032 |
|
|
break; |
1033 |
|
|
} |
1034 |
gbeauche |
1.10 |
nqdmisc_tvect = FindLibSymbol("\014InterfaceLib", "\007NQDMisc"); |
1035 |
cebix |
1.1 |
D(bug("NQDMisc TVECT at %08lx\n", nqdmisc_tvect)); |
1036 |
|
|
if (nqdmisc_tvect == 0) { |
1037 |
|
|
printf("FATAL: VideoDoDriverIO(): Can't find NQDMisc()\n"); |
1038 |
|
|
err = -1; |
1039 |
|
|
break; |
1040 |
|
|
} |
1041 |
|
|
|
1042 |
|
|
private_data = new VidLocals; |
1043 |
gbeauche |
1.11 |
private_data->gammaTable = 0; |
1044 |
gbeauche |
1.12 |
private_data->regEntryID = Mac_sysalloc(sizeof(RegEntryID)); |
1045 |
|
|
if (private_data->regEntryID == 0) { |
1046 |
|
|
printf("FATAL: VideoDoDriverIO(): Can't allocate service owner\n"); |
1047 |
|
|
err = -1; |
1048 |
|
|
break; |
1049 |
|
|
} |
1050 |
|
|
Mac2Mac_memcpy(private_data->regEntryID, commandContents + 2, 16); // DriverInitInfo.deviceEntry |
1051 |
cebix |
1.1 |
private_data->interruptsEnabled = false; // Disable interrupts |
1052 |
|
|
break; |
1053 |
|
|
|
1054 |
|
|
case kFinalizeCommand: |
1055 |
|
|
case kSupersededCommand: |
1056 |
gbeauche |
1.12 |
if (private_data != NULL) { |
1057 |
|
|
if (private_data->gammaTable) |
1058 |
|
|
Mac_sysfree(private_data->gammaTable); |
1059 |
|
|
if (private_data->regEntryID) |
1060 |
|
|
Mac_sysfree(private_data->regEntryID); |
1061 |
|
|
} |
1062 |
cebix |
1.1 |
delete private_data; |
1063 |
|
|
private_data = NULL; |
1064 |
|
|
break; |
1065 |
|
|
|
1066 |
|
|
case kOpenCommand: |
1067 |
gbeauche |
1.9 |
err = VideoOpen(commandContents, private_data); |
1068 |
cebix |
1.1 |
break; |
1069 |
|
|
|
1070 |
|
|
case kCloseCommand: |
1071 |
gbeauche |
1.9 |
err = VideoClose(commandContents, private_data); |
1072 |
cebix |
1.1 |
break; |
1073 |
|
|
|
1074 |
|
|
case kControlCommand: |
1075 |
gbeauche |
1.9 |
err = VideoControl(commandContents, private_data); |
1076 |
cebix |
1.1 |
break; |
1077 |
|
|
|
1078 |
|
|
case kStatusCommand: |
1079 |
gbeauche |
1.9 |
err = VideoStatus(commandContents, private_data); |
1080 |
cebix |
1.1 |
break; |
1081 |
|
|
|
1082 |
|
|
case kReadCommand: |
1083 |
|
|
case kWriteCommand: |
1084 |
|
|
break; |
1085 |
|
|
|
1086 |
|
|
case kKillIOCommand: |
1087 |
|
|
err = abortErr; |
1088 |
|
|
break; |
1089 |
|
|
|
1090 |
|
|
default: |
1091 |
|
|
err = paramErr; |
1092 |
|
|
break; |
1093 |
|
|
} |
1094 |
|
|
|
1095 |
|
|
if (commandKind == kImmediateIOCommandKind) |
1096 |
|
|
return err; |
1097 |
|
|
else |
1098 |
|
|
return IOCommandIsComplete(commandID, err); |
1099 |
|
|
} |