52 |
|
bool luminance_mapping; // Luminance mapping on/off |
53 |
|
bool interrupts_enabled; // VBL interrupts on/off |
54 |
|
uint32 gamma_table; // Mac address of gamma table |
55 |
+ |
int alloc_gamma_table_size; // Allocated size of gamma table |
56 |
|
uint16 current_mode; // Currently selected depth/resolution |
57 |
|
uint32 current_id; |
58 |
|
uint16 preferred_mode; // Preferred depth/resolution |
59 |
|
uint32 preferred_id; |
60 |
< |
uint32 sp; // Mac address of Slot Manager parameter block |
60 |
> |
uint32 slot_param; // Mac address of Slot Manager parameter block |
61 |
|
} VidLocal; |
62 |
|
|
63 |
|
|
134 |
|
|
135 |
|
static void set_gray_palette(void) |
136 |
|
{ |
137 |
< |
if (!IsDirectMode(VidLocal.current_mode)) { |
138 |
< |
for (int i=0; i<256; i++) { |
139 |
< |
VidLocal.palette[i * 3 + 0] = 127; |
140 |
< |
VidLocal.palette[i * 3 + 1] = 127; |
141 |
< |
VidLocal.palette[i * 3 + 2] = 127; |
137 |
> |
for (int i=0; i<256; i++) { |
138 |
> |
VidLocal.palette[i * 3 + 0] = 127; |
139 |
> |
VidLocal.palette[i * 3 + 1] = 127; |
140 |
> |
VidLocal.palette[i * 3 + 2] = 127; |
141 |
> |
} |
142 |
> |
video_set_palette(VidLocal.palette); |
143 |
> |
} |
144 |
> |
|
145 |
> |
|
146 |
> |
/* |
147 |
> |
* Load gamma-corrected black-to-white ramp to palette for direct-color mode |
148 |
> |
*/ |
149 |
> |
|
150 |
> |
static void load_ramp_palette(void) |
151 |
> |
{ |
152 |
> |
// Find tables for gamma correction |
153 |
> |
uint8 *red_gamma, *green_gamma, *blue_gamma; |
154 |
> |
bool have_gamma = false; |
155 |
> |
int data_width = 0; |
156 |
> |
if (VidLocal.gamma_table) { |
157 |
> |
uint32 table = VidLocal.gamma_table; |
158 |
> |
red_gamma = Mac2HostAddr(table + gFormulaData + ReadMacInt16(table + gFormulaSize)); |
159 |
> |
int chan_cnt = ReadMacInt16(table + gChanCnt); |
160 |
> |
if (chan_cnt == 1) |
161 |
> |
green_gamma = blue_gamma = red_gamma; |
162 |
> |
else { |
163 |
> |
int ofs = ReadMacInt16(table + gDataCnt); |
164 |
> |
green_gamma = red_gamma + ofs; |
165 |
> |
blue_gamma = green_gamma + ofs; |
166 |
> |
} |
167 |
> |
data_width = ReadMacInt16(table + gDataWidth); |
168 |
> |
have_gamma = true; |
169 |
> |
} |
170 |
> |
|
171 |
> |
int num = (VidLocal.desc->mode.depth == VDEPTH_16BIT ? 32 : 256); |
172 |
> |
uint8 *p = VidLocal.palette; |
173 |
> |
for (int i=0; i<num; i++) { |
174 |
> |
uint8 red = (i * 256 / num), green = red, blue = red; |
175 |
> |
if (have_gamma) { |
176 |
> |
red = red_gamma[red >> (8 - data_width)]; |
177 |
> |
green = green_gamma[green >> (8 - data_width)]; |
178 |
> |
blue = blue_gamma[blue >> (8 - data_width)]; |
179 |
> |
} |
180 |
> |
*p++ = red; |
181 |
> |
*p++ = green; |
182 |
> |
*p++ = blue; |
183 |
> |
} |
184 |
> |
|
185 |
> |
video_set_palette(VidLocal.palette); |
186 |
> |
} |
187 |
> |
|
188 |
> |
|
189 |
> |
/* |
190 |
> |
* Allocate gamma table of specified size |
191 |
> |
*/ |
192 |
> |
|
193 |
> |
static bool allocate_gamma_table(int size) |
194 |
> |
{ |
195 |
> |
M68kRegisters r; |
196 |
> |
|
197 |
> |
if (size > VidLocal.alloc_gamma_table_size) { |
198 |
> |
if (VidLocal.gamma_table) { |
199 |
> |
r.a[0] = VidLocal.gamma_table; |
200 |
> |
Execute68kTrap(0xa01f, &r); // DisposePtr() |
201 |
> |
VidLocal.gamma_table = 0; |
202 |
> |
VidLocal.alloc_gamma_table_size = 0; |
203 |
|
} |
204 |
< |
video_set_palette(VidLocal.palette); |
204 |
> |
r.d[0] = size; |
205 |
> |
Execute68kTrap(0xa71e, &r); // NewPtrSysClear() |
206 |
> |
if (r.a[0] == 0) |
207 |
> |
return false; |
208 |
> |
VidLocal.gamma_table = r.a[0]; |
209 |
> |
VidLocal.alloc_gamma_table_size = size; |
210 |
|
} |
211 |
+ |
return true; |
212 |
+ |
} |
213 |
+ |
|
214 |
+ |
|
215 |
+ |
/* |
216 |
+ |
* Set gamma table (0 = build linear ramp) |
217 |
+ |
*/ |
218 |
+ |
|
219 |
+ |
static bool set_gamma_table(uint32 user_table) |
220 |
+ |
{ |
221 |
+ |
if (user_table == 0) { // Build linear ramp, 256 entries |
222 |
+ |
|
223 |
+ |
// Allocate new table, if necessary |
224 |
+ |
if (!allocate_gamma_table(SIZEOF_GammaTbl + 256)) |
225 |
+ |
return memFullErr; |
226 |
+ |
uint32 table = VidLocal.gamma_table; |
227 |
+ |
|
228 |
+ |
// Initialize header |
229 |
+ |
WriteMacInt16(table + gVersion, 0); |
230 |
+ |
WriteMacInt16(table + gType, 0); |
231 |
+ |
WriteMacInt16(table + gFormulaSize, 0); |
232 |
+ |
WriteMacInt16(table + gChanCnt, 1); |
233 |
+ |
WriteMacInt16(table + gDataCnt, 256); |
234 |
+ |
WriteMacInt16(table + gDataWidth, 8); |
235 |
+ |
|
236 |
+ |
// Build ramp |
237 |
+ |
uint32 p = table + gFormulaData; |
238 |
+ |
for (int i=0; i<256; i++) |
239 |
+ |
WriteMacInt8(p + i, i); |
240 |
+ |
|
241 |
+ |
} else { // User-supplied gamma table |
242 |
+ |
|
243 |
+ |
// Validate header |
244 |
+ |
if (ReadMacInt16(user_table + gVersion)) |
245 |
+ |
return paramErr; |
246 |
+ |
if (ReadMacInt16(user_table + gType)) |
247 |
+ |
return paramErr; |
248 |
+ |
int chan_cnt = ReadMacInt16(user_table + gChanCnt); |
249 |
+ |
if (chan_cnt != 1 && chan_cnt != 3) |
250 |
+ |
return paramErr; |
251 |
+ |
int data_width = ReadMacInt16(user_table + gDataWidth); |
252 |
+ |
if (data_width > 8) |
253 |
+ |
return paramErr; |
254 |
+ |
int data_cnt = ReadMacInt16(user_table + gDataCnt); |
255 |
+ |
if (data_cnt != (1 << data_width)) |
256 |
+ |
return paramErr; |
257 |
+ |
|
258 |
+ |
// Allocate new table, if necessary |
259 |
+ |
int size = SIZEOF_GammaTbl + ReadMacInt16(user_table + gFormulaSize) + chan_cnt * data_cnt; |
260 |
+ |
if (!allocate_gamma_table(size)) |
261 |
+ |
return memFullErr; |
262 |
+ |
uint32 table = VidLocal.gamma_table; |
263 |
+ |
|
264 |
+ |
// Copy table |
265 |
+ |
Mac2Mac_memcpy(table, user_table, size); |
266 |
+ |
} |
267 |
+ |
|
268 |
+ |
if (IsDirectMode(VidLocal.current_mode)) |
269 |
+ |
load_ramp_palette(); |
270 |
+ |
|
271 |
+ |
return true; |
272 |
|
} |
273 |
|
|
274 |
|
|
299 |
|
Execute68kTrap(0xa71e, &r); // NewPtrSysClear() |
300 |
|
if (r.a[0] == 0) |
301 |
|
return memFullErr; |
302 |
< |
VidLocal.sp = r.a[0]; |
303 |
< |
D(bug("SPBlock at %08x\n", VidLocal.sp)); |
302 |
> |
VidLocal.slot_param = r.a[0]; |
303 |
> |
D(bug("SPBlock at %08x\n", VidLocal.slot_param)); |
304 |
|
|
305 |
|
// Find and set default gamma table |
306 |
< |
VidLocal.gamma_table = 0; //!! |
306 |
> |
VidLocal.gamma_table = 0; |
307 |
> |
VidLocal.alloc_gamma_table_size = 0; |
308 |
> |
set_gamma_table(0); |
309 |
|
|
310 |
|
// Init color palette (solid gray) |
311 |
|
set_gray_palette(); |
348 |
|
return noErr; |
349 |
|
} |
350 |
|
|
351 |
< |
case cscSetEntries: { // Set palette |
352 |
< |
D(bug(" SetEntries table %08x, count %d, start %d\n", ReadMacInt32(param + csTable), ReadMacInt16(param + csCount), ReadMacInt16(param + csStart))); |
353 |
< |
if (IsDirectMode(VidLocal.current_mode)) |
351 |
> |
case cscSetEntries: // Set palette |
352 |
> |
case cscDirectSetEntries: { |
353 |
> |
D(bug(" (Direct)SetEntries table %08x, count %d, start %d\n", ReadMacInt32(param + csTable), ReadMacInt16(param + csCount), ReadMacInt16(param + csStart))); |
354 |
> |
bool is_direct = IsDirectMode(VidLocal.current_mode); |
355 |
> |
if (code == cscSetEntries && is_direct) |
356 |
> |
return controlErr; |
357 |
> |
if (code == cscDirectSetEntries && !is_direct) |
358 |
|
return controlErr; |
359 |
|
|
360 |
|
uint32 s_pal = ReadMacInt32(param + csTable); // Source palette |
364 |
|
if (s_pal == 0 || count > 255) |
365 |
|
return paramErr; |
366 |
|
|
367 |
+ |
// Find tables for gamma correction |
368 |
+ |
uint8 *red_gamma, *green_gamma, *blue_gamma; |
369 |
+ |
bool have_gamma = false; |
370 |
+ |
int data_width = 0; |
371 |
+ |
if (VidLocal.gamma_table) { |
372 |
+ |
uint32 table = VidLocal.gamma_table; |
373 |
+ |
red_gamma = Mac2HostAddr(table + gFormulaData + ReadMacInt16(table + gFormulaSize)); |
374 |
+ |
int chan_cnt = ReadMacInt16(table + gChanCnt); |
375 |
+ |
if (chan_cnt == 1) |
376 |
+ |
green_gamma = blue_gamma = red_gamma; |
377 |
+ |
else { |
378 |
+ |
int ofs = ReadMacInt16(table + gDataCnt); |
379 |
+ |
green_gamma = red_gamma + ofs; |
380 |
+ |
blue_gamma = green_gamma + ofs; |
381 |
+ |
} |
382 |
+ |
data_width = ReadMacInt16(table + gDataWidth); |
383 |
+ |
have_gamma = true; |
384 |
+ |
} |
385 |
+ |
|
386 |
+ |
// Convert palette |
387 |
|
if (start == 0xffff) { // Indexed |
388 |
|
for (uint32 i=0; i<=count; i++) { |
389 |
|
d_pal = VidLocal.palette + (ReadMacInt16(s_pal) & 0xff) * 3; |
390 |
|
uint8 red = (uint16)ReadMacInt16(s_pal + 2) >> 8; |
391 |
|
uint8 green = (uint16)ReadMacInt16(s_pal + 4) >> 8; |
392 |
|
uint8 blue = (uint16)ReadMacInt16(s_pal + 6) >> 8; |
393 |
< |
if (VidLocal.luminance_mapping) |
393 |
> |
if (VidLocal.luminance_mapping && !is_direct) |
394 |
|
red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16; |
395 |
< |
//!! gamma correction |
395 |
> |
if (have_gamma) { |
396 |
> |
red = red_gamma[red >> (8 - data_width)]; |
397 |
> |
green = green_gamma[green >> (8 - data_width)]; |
398 |
> |
blue = blue_gamma[blue >> (8 - data_width)]; |
399 |
> |
} |
400 |
|
*d_pal++ = red; |
401 |
|
*d_pal++ = green; |
402 |
|
*d_pal++ = blue; |
410 |
|
uint8 red = (uint16)ReadMacInt16(s_pal + 2) >> 8; |
411 |
|
uint8 green = (uint16)ReadMacInt16(s_pal + 4) >> 8; |
412 |
|
uint8 blue = (uint16)ReadMacInt16(s_pal + 6) >> 8; |
413 |
< |
if (VidLocal.luminance_mapping) |
413 |
> |
if (VidLocal.luminance_mapping && !is_direct) |
414 |
|
red = green = blue = (red * 0x4ccc + green * 0x970a + blue * 0x1c29) >> 16; |
415 |
< |
//!! gamma correction |
415 |
> |
if (have_gamma) { |
416 |
> |
red = red_gamma[red >> (8 - data_width)]; |
417 |
> |
green = green_gamma[green >> (8 - data_width)]; |
418 |
> |
blue = blue_gamma[blue >> (8 - data_width)]; |
419 |
> |
} |
420 |
|
*d_pal++ = red; |
421 |
|
*d_pal++ = green; |
422 |
|
*d_pal++ = blue; |
427 |
|
return noErr; |
428 |
|
} |
429 |
|
|
430 |
< |
case cscSetGamma: // Set gamma table |
431 |
< |
D(bug(" SetGamma\n")); |
432 |
< |
//!! |
433 |
< |
return controlErr; |
430 |
> |
case cscSetGamma: { // Set gamma table |
431 |
> |
uint32 user_table = ReadMacInt32(param + csGTable); |
432 |
> |
D(bug(" SetGamma %08x\n", user_table)); |
433 |
> |
return set_gamma_table(user_table) ? noErr : memFullErr; |
434 |
> |
} |
435 |
|
|
436 |
|
case cscGrayPage: { // Fill page with dithered gray pattern |
437 |
|
D(bug(" GrayPage %d\n", ReadMacInt16(param + csPage))); |
458 |
|
p += VidLocal.desc->mode.bytes_per_row; |
459 |
|
pat = ~pat; |
460 |
|
} |
461 |
< |
//!! if direct mode, load gamma table to CLUT |
461 |
> |
|
462 |
> |
if (IsDirectMode(VidLocal.current_mode)) |
463 |
> |
load_ramp_palette(); |
464 |
> |
|
465 |
|
return noErr; |
466 |
|
} |
467 |
|
|
505 |
|
WriteMacInt32(param + csBaseAddr, frame_base); |
506 |
|
|
507 |
|
M68kRegisters r; |
508 |
< |
uint32 sp = VidLocal.sp; |
508 |
> |
uint32 sp = VidLocal.slot_param; |
509 |
|
r.a[0] = sp; |
510 |
|
|
511 |
|
// Find functional sResource for this display |
653 |
|
return noErr; |
654 |
|
|
655 |
|
case cscGetGamma: |
656 |
< |
D(bug(" GetGamma -> \n")); |
657 |
< |
//!! |
658 |
< |
return statusErr; |
656 |
> |
D(bug(" GetGamma -> %08x\n", VidLocal.gamma_table)); |
657 |
> |
WriteMacInt32(param + csGTable, VidLocal.gamma_table); |
658 |
> |
return noErr; |
659 |
|
|
660 |
|
case cscGetDefaultMode: // Get default color depth |
661 |
|
D(bug(" GetDefaultMode -> %04x\n", VidLocal.preferred_mode)); |