Cygwin support, using SDL.
[btb/d2x.git] / unused / win95 / palette.c
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
72 void grwin_set_winpalette(LPDIRECTDRAW lpdd, LPDIRECTDRAWPALETTE lpDDPal)
73 {
74         _lpDDPalActive = lpDDPal;
75         lpDD = lpdd;
76         
77 }
78
79
80 LPDIRECTDRAWPALETTE grwin_get_winpalette(void)
81 {
82         return _lpDDPalActive;
83
84 }
85
86
87 void grwin_cleanup_palette()
88 {
89         if (hPalGDI) DeleteObject(hPalGDI);
90 }
91
92
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
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
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
142 int gr_palette_get_gamma()
143 {
144         return gr_palette_gamma_param;
145 }
146
147
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.
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
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
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
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
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
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
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
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
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
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
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
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
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
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