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.
15 #define WIN32_LEAN_AND_MEAN
36 typedef struct LOGPAL256 {
39 PALETTEENTRY ScratchPal[256];
43 // Special --------------------------------------------------------------------
44 extern int gr_installed;
47 // Globals --------------------------------------------------------------------
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
53 ubyte gr_palette_gamma = 0;
54 int gr_palette_gamma_param = 0;
55 ubyte gr_palette_faded_out = 1;
57 int grd_fades_disabled=0; // Used to skip fading for development
59 static LPDIRECTDRAWPALETTE _lpDDPalActive = 0;
60 static LPDIRECTDRAW lpDD = NULL;
62 static BOOL PalGDI = FALSE;
63 static HPALETTE hPalGDI = 0;
64 static LOGPAL256 PalGDIData;
67 void ClearSystemPalette();
70 // Functions ------------------------------------------------------------------
72 void grwin_set_winpalette(LPDIRECTDRAW lpdd, LPDIRECTDRAWPALETTE lpDDPal)
74 _lpDDPalActive = lpDDPal;
80 LPDIRECTDRAWPALETTE grwin_get_winpalette(void)
82 return _lpDDPalActive;
87 void grwin_cleanup_palette()
89 if (hPalGDI) DeleteObject(hPalGDI);
93 void grwin_set_palette_exclusive(int yes)
97 if (hPalGDI) DeleteObject(hPalGDI);
103 ClearSystemPalette();
106 PalGDIData.ver = 0x300;
107 PalGDIData.num = 256;
108 hPalGDI = CreatePalette((PLOGPALETTE)&PalGDIData);
110 hdc = GetDC(GetLibraryWindow());
111 SelectPalette(hdc, hPalGDI, FALSE);
112 ReleaseDC(GetLibraryWindow(), hdc);
117 void grwin_gdi_realizepal(HDC hdc)
120 SelectPalette(hdc, hPalGDI, FALSE);
126 // ----------------------------------------------------------------------------
128 void gr_palette_set_gamma( int gamma )
130 if ( gamma < 0 ) gamma = 0;
131 if ( gamma > 8 ) gamma = 8;
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 );
142 int gr_palette_get_gamma()
144 return gr_palette_gamma_param;
148 void gr_use_palette_table( char * filename )
153 fp = cfopen( filename, "rb" );
155 Error("Can't open palette file <%s>",filename);
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 );
163 // This is the TRANSPARENCY COLOR
164 for (i=0; i<GR_FADE_LEVELS; i++ ) {
165 gr_fade_table[i*256+255] = 255;
170 #define SQUARE(x) ((x)*(x))
172 #define MAX_COMPUTED_COLORS 32
174 int Num_computed_colors=0;
177 ubyte r,g,b,color_num;
180 color_record Computed_colors[MAX_COMPUTED_COLORS];
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.
185 void add_computed_color(int r, int g, int b, int color_num)
189 if (Num_computed_colors < MAX_COMPUTED_COLORS) {
190 add_index = Num_computed_colors;
191 Num_computed_colors++;
193 add_index = (rand() * MAX_COMPUTED_COLORS) >> 15;
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;
201 void init_computed_colors(void)
205 for (i=0; i<MAX_COMPUTED_COLORS; i++)
206 Computed_colors[i].r = 255; // Make impossible to match.
209 int gr_find_closest_color( int r, int g, int b )
212 int best_value, best_index, value;
214 if (Num_computed_colors == 0)
215 init_computed_colors();
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) {
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;
229 return Computed_colors[i].color_num;
236 best_value = SQUARE(r-gr_palette[0])+SQUARE(g-gr_palette[1])+SQUARE(b-gr_palette[2]);
239 add_computed_color(r, g, b, best_index);
243 // only go to 255, 'cause we dont want to check the transparent color.
244 for (i=1; i<254; i++ ) {
246 value = SQUARE(r-gr_palette[j])+SQUARE(g-gr_palette[j+1])+SQUARE(b-gr_palette[j+2]);
247 if ( value < best_value ) {
249 add_computed_color(r, g, b, i);
256 add_computed_color(r, g, b, best_index);
260 int gr_find_closest_color_15bpp( int rgb )
262 return gr_find_closest_color( ((rgb>>10)&31)*2, ((rgb>>5)&31)*2, (rgb&31)*2 );
266 int gr_find_closest_color_current( int r, int g, int b )
269 int best_value, best_index, value;
275 best_value = SQUARE(r-gr_current_pal[0])+SQUARE(g-gr_current_pal[1])+SQUARE(b-gr_current_pal[2]);
281 // only go to 255, 'cause we dont want to check the transparent color.
282 for (i=1; i<254; i++ ) {
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 ) {
296 static int last_r=0, last_g=0, last_b=0;
298 void gr_palette_step_up( int r, int g, int b )
305 Assert(_lpDDPalActive!=0);
307 if (gr_palette_faded_out) return;
309 if ( (r==last_r) && (g==last_g) && (b==last_b) ) return;
316 for (i=0; i<256; i++ ) {
317 temp = (int)(*p++) + r + gr_palette_gamma;
319 else if (temp>63) temp=63;
320 PalGDIData.ScratchPal[i].peRed = temp << 2;
321 temp = (int)(*p++) + g + gr_palette_gamma;
323 else if (temp>63) temp=63;
324 PalGDIData.ScratchPal[i].peGreen = temp << 2;
325 temp = (int)(*p++) + b + gr_palette_gamma;
327 else if (temp>63) temp=63;
328 PalGDIData.ScratchPal[i].peBlue = temp << 2;
329 PalGDIData.ScratchPal[i].peFlags = PC_NOCOLLAPSE;
333 ddresult = IDirectDrawPalette_SetEntries(_lpDDPalActive, 0, 0, 256, PalGDIData.ScratchPal);
334 Assert(ddresult == DD_OK);
339 hdc = GetDC(GetLibraryWindow());
340 SetPaletteEntries(hPalGDI, 0, PalGDIData.num, PalGDIData.ScratchPal);
342 ReleaseDC(GetLibraryWindow(), hdc);
347 void gr_palette_clear()
352 Assert(_lpDDPalActive!=0);
355 for (i = 0; i < 256; i++)
357 PalGDIData.ScratchPal[i].peRed =
358 PalGDIData.ScratchPal[i].peBlue =
359 PalGDIData.ScratchPal[i].peGreen = 0;
360 PalGDIData.ScratchPal[i].peFlags = 0;
364 ddresult = IDirectDrawPalette_SetEntries(_lpDDPalActive, 0,
366 PalGDIData.ScratchPal);
367 Assert(ddresult == DD_OK);
372 hdc = GetDC(GetLibraryWindow());
373 SetPaletteEntries(hPalGDI, 0, PalGDIData.num, PalGDIData.ScratchPal);
375 ReleaseDC(GetLibraryWindow(), hdc);
378 gr_palette_faded_out = 1;
379 if (GRMODEINFO(emul)) DDClearDisplay();
383 void gr_palette_load( ubyte * pal )
389 Assert(_lpDDPalActive!=0);
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;
408 ddresult = IDirectDrawPalette_SetEntries(_lpDDPalActive, 0,
410 PalGDIData.ScratchPal);
411 Assert(ddresult == DD_OK);
416 hdc = GetDC(GetLibraryWindow());
417 SetPaletteEntries(hPalGDI, 0, PalGDIData.num, PalGDIData.ScratchPal);
419 ReleaseDC(GetLibraryWindow(), hdc);
422 gr_palette_faded_out = 0;
424 init_computed_colors();
427 extern void gr_sync_display(void);
429 int gr_palette_fade_out(ubyte *pal, int nsteps, int allow_keys )
434 fix fade_palette[768];
435 fix fade_palette_delta[768];
437 allow_keys = allow_keys;
439 Assert(_lpDDPalActive!=0);
441 if (gr_palette_faded_out) return 0;
444 if (grd_fades_disabled) {
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;
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;
477 IDirectDraw_WaitForVerticalBlank(lpDD, DDWAITVB_BLOCKBEGIN, NULL);
478 ddresult = IDirectDrawPalette_SetEntries(_lpDDPalActive, 0,
480 PalGDIData.ScratchPal);
481 Assert(ddresult == DD_OK);
486 hdc = GetDC(GetLibraryWindow());
487 SetPaletteEntries(hPalGDI, 0, PalGDIData.num, PalGDIData.ScratchPal);
489 ReleaseDC(GetLibraryWindow(), hdc);
492 gr_palette_faded_out = 1;
494 if (GRMODEINFO(emul)) DDClearDisplay();
499 int gr_palette_fade_in(ubyte *pal, int nsteps, int allow_keys)
504 fix fade_palette[768];
505 fix fade_palette_delta[768];
507 allow_keys = allow_keys;
509 Assert(_lpDDPalActive!=0);
511 if (!gr_palette_faded_out) return 0;
514 if (grd_fades_disabled) {
515 gr_palette_load(pal);
520 for (i=0; i<768; i++ ) {
521 gr_current_pal[i] = pal[i];
523 fade_palette_delta[i] = i2f(pal[i]+gr_palette_gamma) / nsteps;
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);
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;
551 IDirectDraw_WaitForVerticalBlank(lpDD, DDWAITVB_BLOCKBEGIN, NULL);
552 ddresult = IDirectDrawPalette_SetEntries(_lpDDPalActive, 0,
554 PalGDIData.ScratchPal);
555 Assert (ddresult == DD_OK);
560 hdc = GetDC(GetLibraryWindow());
561 SetPaletteEntries(hPalGDI, 0, PalGDIData.num, PalGDIData.ScratchPal);
563 ReleaseDC(GetLibraryWindow(), hdc);
567 gr_palette_faded_out = 0;
571 void gr_make_cthru_table(ubyte * table, ubyte r, ubyte g, ubyte b )
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 );
587 void gr_palette_read(ubyte * palette)
592 Assert(_lpDDPalActive!=0);
595 ddresult = IDirectDrawPalette_GetEntries(_lpDDPalActive, 0, 0, 256, PalGDIData.ScratchPal);
596 Assert(ddresult == DD_OK);
599 SetPaletteEntries(hPalGDI, 0, 256, PalGDIData.ScratchPal);
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;
611 void gr_copy_palette(ubyte *gr_palette, ubyte *pal, int size)
613 memcpy(gr_palette, pal, size);
615 Num_computed_colors = 0;
619 // GDI Palette Functions taken from ancient WinG version
621 void ClearSystemPalette()
623 LOGPAL256 palette = {
627 HPALETTE screenpal = 0;
631 // Reset system palette to black to quicken WinG.
632 for (counter = 0; counter < 256; counter++)
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;
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);