dxx-rebirth/unused/win95/palette.c
Bradley Bell 9bd1ba7c47 This commit was generated by cvs2svn to compensate for changes in r2,
which included commits to RCS files with non-trunk default branches.
2001-01-19 03:30:16 +00:00

666 lines
15 KiB
C

/*
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
*/
#define WIN95
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <conio.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include "ddraw.h"
#include "types.h"
#include "mem.h"
#include "gr.h"
#include "cfile.h"
#include "error.h"
#include "mono.h"
#include "fix.h"
#include "key.h"
#include "winapp.h"
#include "dd.h"
typedef struct LOGPAL256 {
WORD ver;
WORD num;
PALETTEENTRY ScratchPal[256];
} LOGPAL256;
// Special --------------------------------------------------------------------
extern int gr_installed;
// Globals --------------------------------------------------------------------
ubyte gr_palette[256*3]; // Main Palette in RGB
ubyte gr_current_pal[256*3]; // Current Valid Palette in RGB
ubyte gr_fade_table[256*34]; // Fade Palette Table in RGB
ubyte gr_palette_gamma = 0;
int gr_palette_gamma_param = 0;
ubyte gr_palette_faded_out = 1;
int grd_fades_disabled=0; // Used to skip fading for development
static LPDIRECTDRAWPALETTE _lpDDPalActive = 0;
static LPDIRECTDRAW lpDD = NULL;
static BOOL PalGDI = FALSE;
static HPALETTE hPalGDI = 0;
static LOGPAL256 PalGDIData;
void ClearSystemPalette();
// Functions ------------------------------------------------------------------
void grwin_set_winpalette(LPDIRECTDRAW lpdd, LPDIRECTDRAWPALETTE lpDDPal)
{
_lpDDPalActive = lpDDPal;
lpDD = lpdd;
}
LPDIRECTDRAWPALETTE grwin_get_winpalette(void)
{
return _lpDDPalActive;
}
void grwin_cleanup_palette()
{
if (hPalGDI) DeleteObject(hPalGDI);
}
void grwin_set_palette_exclusive(int yes)
{
if (yes) {
PalGDI = FALSE;
if (hPalGDI) DeleteObject(hPalGDI);
hPalGDI = 0;
}
else {
HDC hdc;
ClearSystemPalette();
PalGDI = TRUE;
PalGDIData.ver = 0x300;
PalGDIData.num = 256;
hPalGDI = CreatePalette((PLOGPALETTE)&PalGDIData);
hdc = GetDC(GetLibraryWindow());
SelectPalette(hdc, hPalGDI, FALSE);
ReleaseDC(GetLibraryWindow(), hdc);
}
}
void grwin_gdi_realizepal(HDC hdc)
{
if (PalGDI) {
SelectPalette(hdc, hPalGDI, FALSE);
RealizePalette(hdc);
}
}
// ----------------------------------------------------------------------------
void gr_palette_set_gamma( int gamma )
{
if ( gamma < 0 ) gamma = 0;
if ( gamma > 8 ) gamma = 8;
if (gr_palette_gamma_param != gamma ) {
gr_palette_gamma_param = gamma;
gr_palette_gamma = gamma;
if (!gr_palette_faded_out) {
gr_palette_load( gr_palette );
}
}
}
int gr_palette_get_gamma()
{
return gr_palette_gamma_param;
}
void gr_use_palette_table( char * filename )
{
CFILE *fp;
int i,fsize;
fp = cfopen( filename, "rb" );
if ( fp==NULL)
Error("Can't open palette file <%s>",filename);
fsize = cfilelength( fp );
Assert( fsize == 9472 );
cfread( gr_palette, 256*3, 1, fp );
cfread( gr_fade_table, 256*34, 1, fp );
cfclose(fp);
// This is the TRANSPARENCY COLOR
for (i=0; i<GR_FADE_LEVELS; i++ ) {
gr_fade_table[i*256+255] = 255;
}
}
#define SQUARE(x) ((x)*(x))
#define MAX_COMPUTED_COLORS 32
int Num_computed_colors=0;
typedef struct {
ubyte r,g,b,color_num;
} color_record;
color_record Computed_colors[MAX_COMPUTED_COLORS];
// Add a computed color (by gr_find_closest_color) to list of computed colors in Computed_colors.
// If list wasn't full already, increment Num_computed_colors.
// If was full, replace a random one.
void add_computed_color(int r, int g, int b, int color_num)
{
int add_index;
if (Num_computed_colors < MAX_COMPUTED_COLORS) {
add_index = Num_computed_colors;
Num_computed_colors++;
} else
add_index = (rand() * MAX_COMPUTED_COLORS) >> 15;
Computed_colors[add_index].r = r;
Computed_colors[add_index].g = g;
Computed_colors[add_index].b = b;
Computed_colors[add_index].color_num = color_num;
}
void init_computed_colors(void)
{
int i;
for (i=0; i<MAX_COMPUTED_COLORS; i++)
Computed_colors[i].r = 255; // Make impossible to match.
}
int gr_find_closest_color( int r, int g, int b )
{
int i, j;
int best_value, best_index, value;
if (Num_computed_colors == 0)
init_computed_colors();
// If we've already computed this color, return it!
for (i=0; i<Num_computed_colors; i++)
if (r == Computed_colors[i].r)
if (g == Computed_colors[i].g)
if (b == Computed_colors[i].b) {
if (i > 4) {
color_record trec;
trec = Computed_colors[i-1];
Computed_colors[i-1] = Computed_colors[i];
Computed_colors[i] = trec;
return Computed_colors[i-1].color_num;
}
return Computed_colors[i].color_num;
}
// r &= 63;
// g &= 63;
// b &= 63;
best_value = SQUARE(r-gr_palette[0])+SQUARE(g-gr_palette[1])+SQUARE(b-gr_palette[2]);
best_index = 0;
if (best_value==0) {
add_computed_color(r, g, b, best_index);
return best_index;
}
j=0;
// only go to 255, 'cause we dont want to check the transparent color.
for (i=1; i<254; i++ ) {
j += 3;
value = SQUARE(r-gr_palette[j])+SQUARE(g-gr_palette[j+1])+SQUARE(b-gr_palette[j+2]);
if ( value < best_value ) {
if (value==0) {
add_computed_color(r, g, b, i);
return i;
}
best_value = value;
best_index = i;
}
}
add_computed_color(r, g, b, best_index);
return best_index;
}
int gr_find_closest_color_15bpp( int rgb )
{
return gr_find_closest_color( ((rgb>>10)&31)*2, ((rgb>>5)&31)*2, (rgb&31)*2 );
}
int gr_find_closest_color_current( int r, int g, int b )
{
int i, j;
int best_value, best_index, value;
// r &= 63;
// g &= 63;
// b &= 63;
best_value = SQUARE(r-gr_current_pal[0])+SQUARE(g-gr_current_pal[1])+SQUARE(b-gr_current_pal[2]);
best_index = 0;
if (best_value==0)
return best_index;
j=0;
// only go to 255, 'cause we dont want to check the transparent color.
for (i=1; i<254; i++ ) {
j += 3;
value = SQUARE(r-gr_current_pal[j])+SQUARE(g-gr_current_pal[j+1])+SQUARE(b-gr_current_pal[j+2]);
if ( value < best_value ) {
if (value==0)
return i;
best_value = value;
best_index = i;
}
}
return best_index;
}
static int last_r=0, last_g=0, last_b=0;
void gr_palette_step_up( int r, int g, int b )
{
HRESULT ddresult;
int i;
ubyte *p;
int temp;
Assert(_lpDDPalActive!=0);
if (gr_palette_faded_out) return;
if ( (r==last_r) && (g==last_g) && (b==last_b) ) return;
last_r = r;
last_g = g;
last_b = b;
p=gr_palette;
for (i=0; i<256; i++ ) {
temp = (int)(*p++) + r + gr_palette_gamma;
if (temp<0) temp=0;
else if (temp>63) temp=63;
PalGDIData.ScratchPal[i].peRed = temp << 2;
temp = (int)(*p++) + g + gr_palette_gamma;
if (temp<0) temp=0;
else if (temp>63) temp=63;
PalGDIData.ScratchPal[i].peGreen = temp << 2;
temp = (int)(*p++) + b + gr_palette_gamma;
if (temp<0) temp=0;
else if (temp>63) temp=63;
PalGDIData.ScratchPal[i].peBlue = temp << 2;
PalGDIData.ScratchPal[i].peFlags = PC_NOCOLLAPSE;
}
if (!PalGDI) {
ddresult = IDirectDrawPalette_SetEntries(_lpDDPalActive, 0, 0, 256, PalGDIData.ScratchPal);
Assert(ddresult == DD_OK);
}
else {
HDC hdc;
hdc = GetDC(GetLibraryWindow());
SetPaletteEntries(hPalGDI, 0, PalGDIData.num, PalGDIData.ScratchPal);
RealizePalette(hdc);
ReleaseDC(GetLibraryWindow(), hdc);
}
}
void gr_palette_clear()
{
int i;
HRESULT ddresult;
Assert(_lpDDPalActive!=0);
// Zero out Palette
for (i = 0; i < 256; i++)
{
PalGDIData.ScratchPal[i].peRed =
PalGDIData.ScratchPal[i].peBlue =
PalGDIData.ScratchPal[i].peGreen = 0;
PalGDIData.ScratchPal[i].peFlags = 0;
}
if (!hPalGDI) {
ddresult = IDirectDrawPalette_SetEntries(_lpDDPalActive, 0,
0, 256,
PalGDIData.ScratchPal);
Assert(ddresult == DD_OK);
}
else {
HDC hdc;
hdc = GetDC(GetLibraryWindow());
SetPaletteEntries(hPalGDI, 0, PalGDIData.num, PalGDIData.ScratchPal);
RealizePalette(hdc);
ReleaseDC(GetLibraryWindow(), hdc);
}
gr_palette_faded_out = 1;
if (GRMODEINFO(emul)) DDClearDisplay();
}
void gr_palette_load( ubyte * pal )
{
int i;
ubyte c;
HRESULT ddresult;
Assert(_lpDDPalActive!=0);
for (i=0; i<256; i++ ) {
c = pal[i*3] + gr_palette_gamma;
if ( c > 63 ) c = 63;
PalGDIData.ScratchPal[i].peRed = c << 2;
gr_current_pal[i*3] = pal[i*3];
c = pal[i*3+1] + gr_palette_gamma;
if ( c > 63 ) c = 63;
PalGDIData.ScratchPal[i].peGreen = c << 2;
gr_current_pal[i*3+1] = pal[i*3+1];
c = pal[i*3+2] + gr_palette_gamma;
if ( c > 63 ) c = 63;
PalGDIData.ScratchPal[i].peBlue = c << 2;
gr_current_pal[i*3+2] = pal[i*3+2];
PalGDIData.ScratchPal[i].peFlags = 0;
}
if (!hPalGDI) {
ddresult = IDirectDrawPalette_SetEntries(_lpDDPalActive, 0,
0, 256,
PalGDIData.ScratchPal);
Assert(ddresult == DD_OK);
}
else {
HDC hdc;
hdc = GetDC(GetLibraryWindow());
SetPaletteEntries(hPalGDI, 0, PalGDIData.num, PalGDIData.ScratchPal);
RealizePalette(hdc);
ReleaseDC(GetLibraryWindow(), hdc);
}
gr_palette_faded_out = 0;
init_computed_colors();
}
extern void gr_sync_display(void);
int gr_palette_fade_out(ubyte *pal, int nsteps, int allow_keys )
{
ubyte c;
int i,j;
HRESULT ddresult;
fix fade_palette[768];
fix fade_palette_delta[768];
allow_keys = allow_keys;
Assert(_lpDDPalActive!=0);
if (gr_palette_faded_out) return 0;
#ifndef NDEBUG
if (grd_fades_disabled) {
gr_palette_clear();
return 0;
}
#endif
for (i=0; i<768; i++ ) {
fade_palette[i] = i2f(pal[i]+gr_palette_gamma);
fade_palette_delta[i] = fade_palette[i] / nsteps;
}
for (j=0; j<nsteps; j++ ) {
for (i=0; i<256; i++ ) {
fade_palette[i*3] -= fade_palette_delta[i*3];
if (fade_palette[i*3] < 0) fade_palette[i*3] = 0;
fade_palette[i*3+1] -= fade_palette_delta[i*3+1];
if (fade_palette[i*3+1] < 0) fade_palette[i*3+1] = 0;
fade_palette[i*3+2] -= fade_palette_delta[i*3+2];
if (fade_palette[i*3+2] < 0) fade_palette[i*3+2] = 0;
c = f2i(fade_palette[i*3]);
if ( c > 63 ) c = 63;
PalGDIData.ScratchPal[i].peRed = c << 2;
c = f2i(fade_palette[i*3+1]);
if ( c > 63 ) c = 63;
PalGDIData.ScratchPal[i].peGreen = c << 2;
c = f2i(fade_palette[i*3+2]);
if ( c > 63 ) c = 63;
PalGDIData.ScratchPal[i].peBlue = c << 2;
PalGDIData.ScratchPal[i].peFlags = 0;
}
if (!hPalGDI) {
IDirectDraw_WaitForVerticalBlank(lpDD, DDWAITVB_BLOCKBEGIN, NULL);
ddresult = IDirectDrawPalette_SetEntries(_lpDDPalActive, 0,
0, 256,
PalGDIData.ScratchPal);
Assert(ddresult == DD_OK);
}
else {
HDC hdc;
hdc = GetDC(GetLibraryWindow());
SetPaletteEntries(hPalGDI, 0, PalGDIData.num, PalGDIData.ScratchPal);
RealizePalette(hdc);
ReleaseDC(GetLibraryWindow(), hdc);
}
}
gr_palette_faded_out = 1;
if (GRMODEINFO(emul)) DDClearDisplay();
return 0;
}
int gr_palette_fade_in(ubyte *pal, int nsteps, int allow_keys)
{
HRESULT ddresult;
int i,j;
ubyte c;
fix fade_palette[768];
fix fade_palette_delta[768];
allow_keys = allow_keys;
Assert(_lpDDPalActive!=0);
if (!gr_palette_faded_out) return 0;
#ifndef NDEBUG
if (grd_fades_disabled) {
gr_palette_load(pal);
return 0;
}
#endif
for (i=0; i<768; i++ ) {
gr_current_pal[i] = pal[i];
fade_palette[i] = 0;
fade_palette_delta[i] = i2f(pal[i]+gr_palette_gamma) / nsteps;
}
for (j=0; j<nsteps; j++ ) {
for (i=0; i<256; i++ ) {
fade_palette[i*3] += fade_palette_delta[i*3];
fade_palette[i*3+1] += fade_palette_delta[i*3+1];
fade_palette[i*3+2] += fade_palette_delta[i*3+2];
if (fade_palette[i*3] > i2f(pal[i*3]+gr_palette_gamma) )
fade_palette[i*3] = i2f(pal[i*3]+gr_palette_gamma);
if (fade_palette[i*3+1] > i2f(pal[i*3+1]+gr_palette_gamma) )
fade_palette[i*3+1] = i2f(pal[i*3+1]+gr_palette_gamma);
if (fade_palette[i*3+2] > i2f(pal[i*3+2]+gr_palette_gamma) )
fade_palette[i*3+2] = i2f(pal[i*3+2]+gr_palette_gamma);
c = f2i(fade_palette[i*3]);
if ( c > 63 ) c = 63;
PalGDIData.ScratchPal[i].peRed = c << 2;
c = f2i(fade_palette[i*3+1]);
if ( c > 63 ) c = 63;
PalGDIData.ScratchPal[i].peGreen = c << 2;
c = f2i(fade_palette[i*3+2]);
if ( c > 63 ) c = 63;
PalGDIData.ScratchPal[i].peBlue = c << 2;
PalGDIData.ScratchPal[i].peFlags = 0;
}
if (!hPalGDI) {
IDirectDraw_WaitForVerticalBlank(lpDD, DDWAITVB_BLOCKBEGIN, NULL);
ddresult = IDirectDrawPalette_SetEntries(_lpDDPalActive, 0,
0, 256,
PalGDIData.ScratchPal);
Assert (ddresult == DD_OK);
}
else {
HDC hdc;
hdc = GetDC(GetLibraryWindow());
SetPaletteEntries(hPalGDI, 0, PalGDIData.num, PalGDIData.ScratchPal);
RealizePalette(hdc);
ReleaseDC(GetLibraryWindow(), hdc);
}
}
gr_palette_faded_out = 0;
return 0;
}
void gr_make_cthru_table(ubyte * table, ubyte r, ubyte g, ubyte b )
{
int i;
ubyte r1, g1, b1;
for (i=0; i<256; i++ ) {
r1 = gr_palette[i*3+0] + r;
if ( r1 > 63 ) r1 = 63;
g1 = gr_palette[i*3+1] + g;
if ( g1 > 63 ) g1 = 63;
b1 = gr_palette[i*3+2] + b;
if ( b1 > 63 ) b1 = 63;
table[i] = gr_find_closest_color( r1, g1, b1 );
}
}
void gr_palette_read(ubyte * palette)
{
int i;
HRESULT ddresult;
Assert(_lpDDPalActive!=0);
if (!hPalGDI) {
ddresult = IDirectDrawPalette_GetEntries(_lpDDPalActive, 0, 0, 256, PalGDIData.ScratchPal);
Assert(ddresult == DD_OK);
}
else {
SetPaletteEntries(hPalGDI, 0, 256, PalGDIData.ScratchPal);
}
for (i=0; i<256; i++ ) {
*palette++ = PalGDIData.ScratchPal[i].peRed >> 2;
*palette++ = PalGDIData.ScratchPal[i].peGreen >> 2;
*palette++ = PalGDIData.ScratchPal[i].peBlue >> 2;
}
}
void gr_copy_palette(ubyte *gr_palette, ubyte *pal, int size)
{
memcpy(gr_palette, pal, size);
Num_computed_colors = 0;
}
// GDI Palette Functions taken from ancient WinG version
void ClearSystemPalette()
{
LOGPAL256 palette = {
0x300,
256,
};
HPALETTE screenpal = 0;
HDC screenDC;
int counter;
// Reset system palette to black to quicken WinG.
for (counter = 0; counter < 256; counter++)
{
palette.ScratchPal[counter].peRed = 0;
palette.ScratchPal[counter].peGreen = 0;
palette.ScratchPal[counter].peBlue = 0;
palette.ScratchPal[counter].peFlags = PC_NOCOLLAPSE;
}
// Create, select, realize, and deselect/delete palette.
screenDC = GetDC(NULL);
screenpal = CreatePalette((LOGPALETTE*)&palette);
screenpal = SelectPalette(screenDC, screenpal, FALSE);
RealizePalette(screenDC);
screenpal = SelectPalette(screenDC, screenpal, FALSE);
DeleteObject(screenpal);
ReleaseDC(NULL, screenDC);
}