1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
12 */
13
14 #define WIN95
15 #define WIN32_LEAN_AND_MEAN
16 #include <windows.h>
17
18 #include <conio.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <io.h>
22
23 #include "ddraw.h"
24
25 #include "types.h"
26 #include "mem.h"
27 #include "gr.h"
28 #include "cfile.h"
29 #include "error.h"
30 #include "mono.h"
31 #include "fix.h"
32 #include "key.h"
33 #include "winapp.h"
34 #include "dd.h"
35
36 typedef struct LOGPAL256 {
37 WORD ver;
38 WORD num;
39 PALETTEENTRY ScratchPal[256];
40 } LOGPAL256;
41
42
43 // Special --------------------------------------------------------------------
44 extern int gr_installed;
45
46
47 // Globals --------------------------------------------------------------------
48
49 ubyte gr_palette[256*3]; // Main Palette in RGB
50 ubyte gr_current_pal[256*3]; // Current Valid Palette in RGB
51 ubyte gr_fade_table[256*34]; // Fade Palette Table in RGB
52
53 ubyte gr_palette_gamma = 0;
54 int gr_palette_gamma_param = 0;
55 ubyte gr_palette_faded_out = 1;
56
57 int grd_fades_disabled=0; // Used to skip fading for development
58
59 static LPDIRECTDRAWPALETTE _lpDDPalActive = 0;
60 static LPDIRECTDRAW lpDD = NULL;
61
62 static BOOL PalGDI = FALSE;
63 static HPALETTE hPalGDI = 0;
64 static LOGPAL256 PalGDIData;
65
66
67 void ClearSystemPalette();
68
69
70 // Functions ------------------------------------------------------------------
71
grwin_set_winpalette(LPDIRECTDRAW lpdd,LPDIRECTDRAWPALETTE lpDDPal)72 void grwin_set_winpalette(LPDIRECTDRAW lpdd, LPDIRECTDRAWPALETTE lpDDPal)
73 {
74 _lpDDPalActive = lpDDPal;
75 lpDD = lpdd;
76
77 }
78
79
grwin_get_winpalette(void)80 LPDIRECTDRAWPALETTE grwin_get_winpalette(void)
81 {
82 return _lpDDPalActive;
83
84 }
85
86
grwin_cleanup_palette()87 void grwin_cleanup_palette()
88 {
89 if (hPalGDI) DeleteObject(hPalGDI);
90 }
91
92
grwin_set_palette_exclusive(int yes)93 void grwin_set_palette_exclusive(int yes)
94 {
95 if (yes) {
96 PalGDI = FALSE;
97 if (hPalGDI) DeleteObject(hPalGDI);
98 hPalGDI = 0;
99 }
100 else {
101 HDC hdc;
102
103 ClearSystemPalette();
104
105 PalGDI = TRUE;
106 PalGDIData.ver = 0x300;
107 PalGDIData.num = 256;
108 hPalGDI = CreatePalette((PLOGPALETTE)&PalGDIData);
109
110 hdc = GetDC(GetLibraryWindow());
111 SelectPalette(hdc, hPalGDI, FALSE);
112 ReleaseDC(GetLibraryWindow(), hdc);
113 }
114 }
115
116
grwin_gdi_realizepal(HDC hdc)117 void grwin_gdi_realizepal(HDC hdc)
118 {
119 if (PalGDI) {
120 SelectPalette(hdc, hPalGDI, FALSE);
121 RealizePalette(hdc);
122 }
123 }
124
125
126 // ----------------------------------------------------------------------------
127
gr_palette_set_gamma(int gamma)128 void gr_palette_set_gamma( int gamma )
129 {
130 if ( gamma < 0 ) gamma = 0;
131 if ( gamma > 8 ) gamma = 8;
132
133 if (gr_palette_gamma_param != gamma ) {
134 gr_palette_gamma_param = gamma;
135 gr_palette_gamma = gamma;
136 if (!gr_palette_faded_out) {
137 gr_palette_load( gr_palette );
138 }
139 }
140 }
141
gr_palette_get_gamma()142 int gr_palette_get_gamma()
143 {
144 return gr_palette_gamma_param;
145 }
146
147
gr_use_palette_table(char * filename)148 void gr_use_palette_table( char * filename )
149 {
150 CFILE *fp;
151 int i,fsize;
152
153 fp = cfopen( filename, "rb" );
154 if ( fp==NULL)
155 Error("Can't open palette file <%s>",filename);
156
157 fsize = cfilelength( fp );
158 Assert( fsize == 9472 );
159 cfread( gr_palette, 256*3, 1, fp );
160 cfread( gr_fade_table, 256*34, 1, fp );
161 cfclose(fp);
162
163 // This is the TRANSPARENCY COLOR
164 for (i=0; i<GR_FADE_LEVELS; i++ ) {
165 gr_fade_table[i*256+255] = 255;
166 }
167
168 }
169
170 #define SQUARE(x) ((x)*(x))
171
172 #define MAX_COMPUTED_COLORS 32
173
174 int Num_computed_colors=0;
175
176 typedef struct {
177 ubyte r,g,b,color_num;
178 } color_record;
179
180 color_record Computed_colors[MAX_COMPUTED_COLORS];
181
182 // Add a computed color (by gr_find_closest_color) to list of computed colors in Computed_colors.
183 // If list wasn't full already, increment Num_computed_colors.
184 // If was full, replace a random one.
add_computed_color(int r,int g,int b,int color_num)185 void add_computed_color(int r, int g, int b, int color_num)
186 {
187 int add_index;
188
189 if (Num_computed_colors < MAX_COMPUTED_COLORS) {
190 add_index = Num_computed_colors;
191 Num_computed_colors++;
192 } else
193 add_index = (rand() * MAX_COMPUTED_COLORS) >> 15;
194
195 Computed_colors[add_index].r = r;
196 Computed_colors[add_index].g = g;
197 Computed_colors[add_index].b = b;
198 Computed_colors[add_index].color_num = color_num;
199 }
200
init_computed_colors(void)201 void init_computed_colors(void)
202 {
203 int i;
204
205 for (i=0; i<MAX_COMPUTED_COLORS; i++)
206 Computed_colors[i].r = 255; // Make impossible to match.
207 }
208
gr_find_closest_color(int r,int g,int b)209 int gr_find_closest_color( int r, int g, int b )
210 {
211 int i, j;
212 int best_value, best_index, value;
213
214 if (Num_computed_colors == 0)
215 init_computed_colors();
216
217 // If we've already computed this color, return it!
218 for (i=0; i<Num_computed_colors; i++)
219 if (r == Computed_colors[i].r)
220 if (g == Computed_colors[i].g)
221 if (b == Computed_colors[i].b) {
222 if (i > 4) {
223 color_record trec;
224 trec = Computed_colors[i-1];
225 Computed_colors[i-1] = Computed_colors[i];
226 Computed_colors[i] = trec;
227 return Computed_colors[i-1].color_num;
228 }
229 return Computed_colors[i].color_num;
230 }
231
232 // r &= 63;
233 // g &= 63;
234 // b &= 63;
235
236 best_value = SQUARE(r-gr_palette[0])+SQUARE(g-gr_palette[1])+SQUARE(b-gr_palette[2]);
237 best_index = 0;
238 if (best_value==0) {
239 add_computed_color(r, g, b, best_index);
240 return best_index;
241 }
242 j=0;
243 // only go to 255, 'cause we dont want to check the transparent color.
244 for (i=1; i<254; i++ ) {
245 j += 3;
246 value = SQUARE(r-gr_palette[j])+SQUARE(g-gr_palette[j+1])+SQUARE(b-gr_palette[j+2]);
247 if ( value < best_value ) {
248 if (value==0) {
249 add_computed_color(r, g, b, i);
250 return i;
251 }
252 best_value = value;
253 best_index = i;
254 }
255 }
256 add_computed_color(r, g, b, best_index);
257 return best_index;
258 }
259
gr_find_closest_color_15bpp(int rgb)260 int gr_find_closest_color_15bpp( int rgb )
261 {
262 return gr_find_closest_color( ((rgb>>10)&31)*2, ((rgb>>5)&31)*2, (rgb&31)*2 );
263 }
264
265
gr_find_closest_color_current(int r,int g,int b)266 int gr_find_closest_color_current( int r, int g, int b )
267 {
268 int i, j;
269 int best_value, best_index, value;
270
271 // r &= 63;
272 // g &= 63;
273 // b &= 63;
274
275 best_value = SQUARE(r-gr_current_pal[0])+SQUARE(g-gr_current_pal[1])+SQUARE(b-gr_current_pal[2]);
276 best_index = 0;
277 if (best_value==0)
278 return best_index;
279
280 j=0;
281 // only go to 255, 'cause we dont want to check the transparent color.
282 for (i=1; i<254; i++ ) {
283 j += 3;
284 value = SQUARE(r-gr_current_pal[j])+SQUARE(g-gr_current_pal[j+1])+SQUARE(b-gr_current_pal[j+2]);
285 if ( value < best_value ) {
286 if (value==0)
287 return i;
288 best_value = value;
289 best_index = i;
290 }
291 }
292 return best_index;
293 }
294
295
296 static int last_r=0, last_g=0, last_b=0;
297
gr_palette_step_up(int r,int g,int b)298 void gr_palette_step_up( int r, int g, int b )
299 {
300 HRESULT ddresult;
301 int i;
302 ubyte *p;
303 int temp;
304
305 Assert(_lpDDPalActive!=0);
306
307 if (gr_palette_faded_out) return;
308
309 if ( (r==last_r) && (g==last_g) && (b==last_b) ) return;
310
311 last_r = r;
312 last_g = g;
313 last_b = b;
314
315 p=gr_palette;
316 for (i=0; i<256; i++ ) {
317 temp = (int)(*p++) + r + gr_palette_gamma;
318 if (temp<0) temp=0;
319 else if (temp>63) temp=63;
320 PalGDIData.ScratchPal[i].peRed = temp << 2;
321 temp = (int)(*p++) + g + gr_palette_gamma;
322 if (temp<0) temp=0;
323 else if (temp>63) temp=63;
324 PalGDIData.ScratchPal[i].peGreen = temp << 2;
325 temp = (int)(*p++) + b + gr_palette_gamma;
326 if (temp<0) temp=0;
327 else if (temp>63) temp=63;
328 PalGDIData.ScratchPal[i].peBlue = temp << 2;
329 PalGDIData.ScratchPal[i].peFlags = PC_NOCOLLAPSE;
330 }
331
332 if (!PalGDI) {
333 ddresult = IDirectDrawPalette_SetEntries(_lpDDPalActive, 0, 0, 256, PalGDIData.ScratchPal);
334 Assert(ddresult == DD_OK);
335 }
336 else {
337 HDC hdc;
338
339 hdc = GetDC(GetLibraryWindow());
340 SetPaletteEntries(hPalGDI, 0, PalGDIData.num, PalGDIData.ScratchPal);
341 RealizePalette(hdc);
342 ReleaseDC(GetLibraryWindow(), hdc);
343 }
344
345 }
346
gr_palette_clear()347 void gr_palette_clear()
348 {
349 int i;
350 HRESULT ddresult;
351
352 Assert(_lpDDPalActive!=0);
353
354 // Zero out Palette
355 for (i = 0; i < 256; i++)
356 {
357 PalGDIData.ScratchPal[i].peRed =
358 PalGDIData.ScratchPal[i].peBlue =
359 PalGDIData.ScratchPal[i].peGreen = 0;
360 PalGDIData.ScratchPal[i].peFlags = 0;
361 }
362
363 if (!hPalGDI) {
364 ddresult = IDirectDrawPalette_SetEntries(_lpDDPalActive, 0,
365 0, 256,
366 PalGDIData.ScratchPal);
367 Assert(ddresult == DD_OK);
368 }
369 else {
370 HDC hdc;
371
372 hdc = GetDC(GetLibraryWindow());
373 SetPaletteEntries(hPalGDI, 0, PalGDIData.num, PalGDIData.ScratchPal);
374 RealizePalette(hdc);
375 ReleaseDC(GetLibraryWindow(), hdc);
376 }
377
378 gr_palette_faded_out = 1;
379 if (GRMODEINFO(emul)) DDClearDisplay();
380
381 }
382
gr_palette_load(ubyte * pal)383 void gr_palette_load( ubyte * pal )
384 {
385 int i;
386 ubyte c;
387 HRESULT ddresult;
388
389 Assert(_lpDDPalActive!=0);
390
391 for (i=0; i<256; i++ ) {
392 c = pal[i*3] + gr_palette_gamma;
393 if ( c > 63 ) c = 63;
394 PalGDIData.ScratchPal[i].peRed = c << 2;
395 gr_current_pal[i*3] = pal[i*3];
396 c = pal[i*3+1] + gr_palette_gamma;
397 if ( c > 63 ) c = 63;
398 PalGDIData.ScratchPal[i].peGreen = c << 2;
399 gr_current_pal[i*3+1] = pal[i*3+1];
400 c = pal[i*3+2] + gr_palette_gamma;
401 if ( c > 63 ) c = 63;
402 PalGDIData.ScratchPal[i].peBlue = c << 2;
403 gr_current_pal[i*3+2] = pal[i*3+2];
404 PalGDIData.ScratchPal[i].peFlags = 0;
405 }
406
407 if (!hPalGDI) {
408 ddresult = IDirectDrawPalette_SetEntries(_lpDDPalActive, 0,
409 0, 256,
410 PalGDIData.ScratchPal);
411 Assert(ddresult == DD_OK);
412 }
413 else {
414 HDC hdc;
415
416 hdc = GetDC(GetLibraryWindow());
417 SetPaletteEntries(hPalGDI, 0, PalGDIData.num, PalGDIData.ScratchPal);
418 RealizePalette(hdc);
419 ReleaseDC(GetLibraryWindow(), hdc);
420 }
421
422 gr_palette_faded_out = 0;
423
424 init_computed_colors();
425 }
426
427 extern void gr_sync_display(void);
428
gr_palette_fade_out(ubyte * pal,int nsteps,int allow_keys)429 int gr_palette_fade_out(ubyte *pal, int nsteps, int allow_keys )
430 {
431 ubyte c;
432 int i,j;
433 HRESULT ddresult;
434 fix fade_palette[768];
435 fix fade_palette_delta[768];
436
437 allow_keys = allow_keys;
438
439 Assert(_lpDDPalActive!=0);
440
441 if (gr_palette_faded_out) return 0;
442
443 #ifndef NDEBUG
444 if (grd_fades_disabled) {
445 gr_palette_clear();
446 return 0;
447 }
448 #endif
449
450 for (i=0; i<768; i++ ) {
451 fade_palette[i] = i2f(pal[i]+gr_palette_gamma);
452 fade_palette_delta[i] = fade_palette[i] / nsteps;
453 }
454
455
456 for (j=0; j<nsteps; j++ ) {
457 for (i=0; i<256; i++ ) {
458 fade_palette[i*3] -= fade_palette_delta[i*3];
459 if (fade_palette[i*3] < 0) fade_palette[i*3] = 0;
460 fade_palette[i*3+1] -= fade_palette_delta[i*3+1];
461 if (fade_palette[i*3+1] < 0) fade_palette[i*3+1] = 0;
462 fade_palette[i*3+2] -= fade_palette_delta[i*3+2];
463 if (fade_palette[i*3+2] < 0) fade_palette[i*3+2] = 0;
464 c = f2i(fade_palette[i*3]);
465 if ( c > 63 ) c = 63;
466 PalGDIData.ScratchPal[i].peRed = c << 2;
467 c = f2i(fade_palette[i*3+1]);
468 if ( c > 63 ) c = 63;
469 PalGDIData.ScratchPal[i].peGreen = c << 2;
470 c = f2i(fade_palette[i*3+2]);
471 if ( c > 63 ) c = 63;
472 PalGDIData.ScratchPal[i].peBlue = c << 2;
473 PalGDIData.ScratchPal[i].peFlags = 0;
474 }
475
476 if (!hPalGDI) {
477 IDirectDraw_WaitForVerticalBlank(lpDD, DDWAITVB_BLOCKBEGIN, NULL);
478 ddresult = IDirectDrawPalette_SetEntries(_lpDDPalActive, 0,
479 0, 256,
480 PalGDIData.ScratchPal);
481 Assert(ddresult == DD_OK);
482 }
483 else {
484 HDC hdc;
485
486 hdc = GetDC(GetLibraryWindow());
487 SetPaletteEntries(hPalGDI, 0, PalGDIData.num, PalGDIData.ScratchPal);
488 RealizePalette(hdc);
489 ReleaseDC(GetLibraryWindow(), hdc);
490 }
491 }
492 gr_palette_faded_out = 1;
493
494 if (GRMODEINFO(emul)) DDClearDisplay();
495
496 return 0;
497 }
498
gr_palette_fade_in(ubyte * pal,int nsteps,int allow_keys)499 int gr_palette_fade_in(ubyte *pal, int nsteps, int allow_keys)
500 {
501 HRESULT ddresult;
502 int i,j;
503 ubyte c;
504 fix fade_palette[768];
505 fix fade_palette_delta[768];
506
507 allow_keys = allow_keys;
508
509 Assert(_lpDDPalActive!=0);
510
511 if (!gr_palette_faded_out) return 0;
512
513 #ifndef NDEBUG
514 if (grd_fades_disabled) {
515 gr_palette_load(pal);
516 return 0;
517 }
518 #endif
519
520 for (i=0; i<768; i++ ) {
521 gr_current_pal[i] = pal[i];
522 fade_palette[i] = 0;
523 fade_palette_delta[i] = i2f(pal[i]+gr_palette_gamma) / nsteps;
524 }
525
526 for (j=0; j<nsteps; j++ ) {
527 for (i=0; i<256; i++ ) {
528 fade_palette[i*3] += fade_palette_delta[i*3];
529 fade_palette[i*3+1] += fade_palette_delta[i*3+1];
530 fade_palette[i*3+2] += fade_palette_delta[i*3+2];
531 if (fade_palette[i*3] > i2f(pal[i*3]+gr_palette_gamma) )
532 fade_palette[i*3] = i2f(pal[i*3]+gr_palette_gamma);
533 if (fade_palette[i*3+1] > i2f(pal[i*3+1]+gr_palette_gamma) )
534 fade_palette[i*3+1] = i2f(pal[i*3+1]+gr_palette_gamma);
535 if (fade_palette[i*3+2] > i2f(pal[i*3+2]+gr_palette_gamma) )
536 fade_palette[i*3+2] = i2f(pal[i*3+2]+gr_palette_gamma);
537
538 c = f2i(fade_palette[i*3]);
539 if ( c > 63 ) c = 63;
540 PalGDIData.ScratchPal[i].peRed = c << 2;
541 c = f2i(fade_palette[i*3+1]);
542 if ( c > 63 ) c = 63;
543 PalGDIData.ScratchPal[i].peGreen = c << 2;
544 c = f2i(fade_palette[i*3+2]);
545 if ( c > 63 ) c = 63;
546 PalGDIData.ScratchPal[i].peBlue = c << 2;
547 PalGDIData.ScratchPal[i].peFlags = 0;
548 }
549
550 if (!hPalGDI) {
551 IDirectDraw_WaitForVerticalBlank(lpDD, DDWAITVB_BLOCKBEGIN, NULL);
552 ddresult = IDirectDrawPalette_SetEntries(_lpDDPalActive, 0,
553 0, 256,
554 PalGDIData.ScratchPal);
555 Assert (ddresult == DD_OK);
556 }
557 else {
558 HDC hdc;
559
560 hdc = GetDC(GetLibraryWindow());
561 SetPaletteEntries(hPalGDI, 0, PalGDIData.num, PalGDIData.ScratchPal);
562 RealizePalette(hdc);
563 ReleaseDC(GetLibraryWindow(), hdc);
564 }
565 }
566
567 gr_palette_faded_out = 0;
568 return 0;
569 }
570
gr_make_cthru_table(ubyte * table,ubyte r,ubyte g,ubyte b)571 void gr_make_cthru_table(ubyte * table, ubyte r, ubyte g, ubyte b )
572 {
573 int i;
574 ubyte r1, g1, b1;
575
576 for (i=0; i<256; i++ ) {
577 r1 = gr_palette[i*3+0] + r;
578 if ( r1 > 63 ) r1 = 63;
579 g1 = gr_palette[i*3+1] + g;
580 if ( g1 > 63 ) g1 = 63;
581 b1 = gr_palette[i*3+2] + b;
582 if ( b1 > 63 ) b1 = 63;
583 table[i] = gr_find_closest_color( r1, g1, b1 );
584 }
585 }
586
gr_palette_read(ubyte * palette)587 void gr_palette_read(ubyte * palette)
588 {
589 int i;
590 HRESULT ddresult;
591
592 Assert(_lpDDPalActive!=0);
593
594 if (!hPalGDI) {
595 ddresult = IDirectDrawPalette_GetEntries(_lpDDPalActive, 0, 0, 256, PalGDIData.ScratchPal);
596 Assert(ddresult == DD_OK);
597 }
598 else {
599 SetPaletteEntries(hPalGDI, 0, 256, PalGDIData.ScratchPal);
600 }
601
602 for (i=0; i<256; i++ ) {
603 *palette++ = PalGDIData.ScratchPal[i].peRed >> 2;
604 *palette++ = PalGDIData.ScratchPal[i].peGreen >> 2;
605 *palette++ = PalGDIData.ScratchPal[i].peBlue >> 2;
606 }
607 }
608
609
610
gr_copy_palette(ubyte * gr_palette,ubyte * pal,int size)611 void gr_copy_palette(ubyte *gr_palette, ubyte *pal, int size)
612 {
613 memcpy(gr_palette, pal, size);
614
615 Num_computed_colors = 0;
616 }
617
618
619 // GDI Palette Functions taken from ancient WinG version
620
ClearSystemPalette()621 void ClearSystemPalette()
622 {
623 LOGPAL256 palette = {
624 0x300,
625 256,
626 };
627 HPALETTE screenpal = 0;
628 HDC screenDC;
629 int counter;
630
631 // Reset system palette to black to quicken WinG.
632 for (counter = 0; counter < 256; counter++)
633 {
634 palette.ScratchPal[counter].peRed = 0;
635 palette.ScratchPal[counter].peGreen = 0;
636 palette.ScratchPal[counter].peBlue = 0;
637 palette.ScratchPal[counter].peFlags = PC_NOCOLLAPSE;
638 }
639
640 // Create, select, realize, and deselect/delete palette.
641 screenDC = GetDC(NULL);
642 screenpal = CreatePalette((LOGPALETTE*)&palette);
643 screenpal = SelectPalette(screenDC, screenpal, FALSE);
644 RealizePalette(screenDC);
645 screenpal = SelectPalette(screenDC, screenpal, FALSE);
646 DeleteObject(screenpal);
647 ReleaseDC(NULL, screenDC);
648 }
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666