/*-----------------------------------------------------------------------** ** Diablo ** ** Palette file ** ** (C)1995 Condor, Inc. All rights reserved. **-----------------------------------------------------------------------** ** $Header: /Diablo/PALETTE.CPP 2 1/23/97 12:21p Jmorin $ **-----------------------------------------------------------------------*/ #include "diablo.h" #pragma hdrstop #include "storm/h/storm.h" #include "palette.h" #include "engine.h" #include #include "resource.h" /*-----------------------------------------------------------------------** ** extern **-----------------------------------------------------------------------*/ extern char gszProgKey[]; void ErrorDlg(int nDlgId,DWORD dwErr,const char * pszFile,int nLine); /*-----------------------------------------------------------------------** ** File Variables **-----------------------------------------------------------------------*/ static LONG sglGamma = lGAMMA_MAX; static int sgnStaticColors2 = 0; static PALETTEENTRY sgLoad[256]; // original loaded palette -- used as reference // for gamma conversion static PALETTEENTRY sgBase[256]; // palettized version of sgLoad static PALETTEENTRY sgCurr[256]; // palette to be displayed -- includes rotations static const char sgszGamma[] = "Gamma Correction"; static BYTE sgbFadedIn = TRUE; extern "C" { BYTE gbLevelTileEnhanceActive = FALSE; BYTE gbLevelTileContrastTable[256]; BYTE gbLevelTileLumaTable[256]; BYTE gbLevelTileSharpenLightTable[256]; BYTE gbLevelTileAoTable[256]; BYTE gbLevelUnitContrastTable[256]; BYTE gbLevelUnitLumaTable[256]; BYTE gbLevelUnitSharpenLightTable[256]; BYTE gbLevelUnitAoTable[256]; BYTE gbTownWarmFlickerActive = FALSE; BYTE gbTownWarmFlickerTable[4][256]; BYTE gbHudAnimateActive = FALSE; BYTE gbHudHealthOrbTable[4][256]; BYTE gbHudManaOrbTable[4][256]; BYTE gbHudPotionHealthTable[4][256]; BYTE gbHudPotionManaTable[4][256]; BYTE gbHudPotionRejuvTable[4][256]; BYTE gbWorldGoldShimmerActive = FALSE; BYTE gbWorldGoldShimmerTable[4][256]; int gnTownTileX = -1; int gnTownTileY = -1; int gnTownFlickerFrame = 0; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static int PalClamp(int value, int max) { if (value < 0) return 0; if (value > max) return max; return value; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static LONG PalDistance(const PALETTEENTRY *a, int red, int green, int blue) { LONG dr, dg, db; dr = (LONG)a->peRed - red; dg = (LONG)a->peGreen - green; db = (LONG)a->peBlue - blue; return dr * dr + dg * dg + db * db; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static BYTE FindNearestPaletteColor(int red, int green, int blue) { int i; BYTE best; LONG dist, bestDist; best = 1; bestDist = PalDistance(&sgLoad[1], red, green, blue); for (i = 2; i < 256; i++) { dist = PalDistance(&sgLoad[i], red, green, blue); if (dist < bestDist) { bestDist = dist; best = (BYTE)i; } } return best; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void BuildLevelTileEnhanceTables() { int i, max, mid; int red, green, blue, brightness; max = 63; for (i = 0; i < 256; i++) { if (sgLoad[i].peRed > 63 || sgLoad[i].peGreen > 63 || sgLoad[i].peBlue > 63) { max = 255; break; } } mid = max / 2; gbLevelTileContrastTable[0] = 0; gbLevelTileLumaTable[0] = 0; gbLevelTileSharpenLightTable[0] = 0; gbLevelTileAoTable[0] = 0; gbLevelUnitContrastTable[0] = 0; gbLevelUnitLumaTable[0] = 0; gbLevelUnitSharpenLightTable[0] = 0; gbLevelUnitAoTable[0] = 0; for (i = 1; i < 256; i++) { brightness = ((int)sgLoad[i].peRed * 30 + (int)sgLoad[i].peGreen * 59 + (int)sgLoad[i].peBlue * 11) / 100; gbLevelTileLumaTable[i] = (BYTE)((brightness * 255) / max); gbLevelUnitLumaTable[i] = gbLevelTileLumaTable[i]; red = (int)sgLoad[i].peRed + (((int)max - (int)sgLoad[i].peRed) * 6) / 100; green = (int)sgLoad[i].peGreen + (((int)max - (int)sgLoad[i].peGreen) * 6) / 100; blue = (int)sgLoad[i].peBlue + (((int)max - (int)sgLoad[i].peBlue) * 6) / 100; gbLevelTileSharpenLightTable[i] = FindNearestPaletteColor( PalClamp(red, max), PalClamp(green, max), PalClamp(blue, max)); red = ((int)sgLoad[i].peRed * 90) / 100; green = ((int)sgLoad[i].peGreen * 90) / 100; blue = ((int)sgLoad[i].peBlue * 90) / 100; gbLevelTileAoTable[i] = FindNearestPaletteColor( PalClamp(red, max), PalClamp(green, max), PalClamp(blue, max)); red = (int)sgLoad[i].peRed + (((int)max - (int)sgLoad[i].peRed) * 12) / 100; green = (int)sgLoad[i].peGreen + (((int)max - (int)sgLoad[i].peGreen) * 12) / 100; blue = (int)sgLoad[i].peBlue + (((int)max - (int)sgLoad[i].peBlue) * 12) / 100; gbLevelUnitSharpenLightTable[i] = FindNearestPaletteColor( PalClamp(red, max), PalClamp(green, max), PalClamp(blue, max)); red = ((int)sgLoad[i].peRed * 82) / 100; green = ((int)sgLoad[i].peGreen * 82) / 100; blue = ((int)sgLoad[i].peBlue * 82) / 100; gbLevelUnitAoTable[i] = FindNearestPaletteColor( PalClamp(red, max), PalClamp(green, max), PalClamp(blue, max)); if (brightness < max / 5 || brightness > (max * 4) / 5) { gbLevelTileContrastTable[i] = (BYTE)i; gbLevelUnitContrastTable[i] = (BYTE)i; continue; } red = mid + (((int)sgLoad[i].peRed - mid) * 106) / 100; green = mid + (((int)sgLoad[i].peGreen - mid) * 106) / 100; blue = mid + (((int)sgLoad[i].peBlue - mid) * 106) / 100; gbLevelTileContrastTable[i] = FindNearestPaletteColor( PalClamp(red, max), PalClamp(green, max), PalClamp(blue, max)); red = mid + (((int)sgLoad[i].peRed - mid) * 108) / 100; green = mid + (((int)sgLoad[i].peGreen - mid) * 108) / 100; blue = mid + (((int)sgLoad[i].peBlue - mid) * 108) / 100; gbLevelUnitContrastTable[i] = FindNearestPaletteColor( PalClamp(red, max), PalClamp(green, max), PalClamp(blue, max)); } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static int IsWarmTownLightColor(int red, int green, int blue, int brightness, int max) { if (brightness < max / 4) return FALSE; if (red < green || green < blue) return FALSE; if (red - blue < max / 7) return FALSE; if (green - blue < max / 12) return FALSE; return TRUE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void BuildTownWarmFlickerTables() { int i, p, max; int red, green, blue, brightness; static const int sPhaseRed[4] = { 6, 14, 9, -3 }; static const int sPhaseGreen[4] = { 3, 8, 5, -2 }; static const int sPhaseBlue[4] = { -3, -6, -4, 0 }; max = 63; for (i = 0; i < 256; i++) { if (sgLoad[i].peRed > 63 || sgLoad[i].peGreen > 63 || sgLoad[i].peBlue > 63) { max = 255; break; } } for (i = 0; i < 256; i++) { brightness = ((int)sgLoad[i].peRed * 30 + (int)sgLoad[i].peGreen * 59 + (int)sgLoad[i].peBlue * 11) / 100; for (p = 0; p < 4; p++) { if (!IsWarmTownLightColor(sgLoad[i].peRed, sgLoad[i].peGreen, sgLoad[i].peBlue, brightness, max)) { gbTownWarmFlickerTable[p][i] = (BYTE)i; continue; } red = (int)sgLoad[i].peRed + (((int)max - (int)sgLoad[i].peRed) * sPhaseRed[p]) / 100; green = (int)sgLoad[i].peGreen + (((int)max - (int)sgLoad[i].peGreen) * sPhaseGreen[p]) / 100; if (sPhaseBlue[p] < 0) blue = ((int)sgLoad[i].peBlue * (100 + sPhaseBlue[p])) / 100; else blue = (int)sgLoad[i].peBlue + (((int)max - (int)sgLoad[i].peBlue) * sPhaseBlue[p]) / 100; gbTownWarmFlickerTable[p][i] = FindNearestPaletteColor( PalClamp(red, max), PalClamp(green, max), PalClamp(blue, max)); } } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static int IsHudHealthColor(int red, int green, int blue, int brightness, int max) { if (brightness < max / 5) return FALSE; if (red < green - max / 16) return FALSE; if (red < blue - max / 12) return FALSE; return TRUE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static int IsHudManaColor(int red, int green, int blue, int brightness, int max) { if (brightness < max / 5) return FALSE; if (blue < red - max / 16) return FALSE; if (blue < green - max / 12) return FALSE; return TRUE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static int IsHudRejuvColor(int red, int green, int blue, int brightness, int max) { if (brightness < max / 5) return FALSE; if (red < green + max / 14) return FALSE; if (blue < green + max / 14) return FALSE; return TRUE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static int HudShiftChannel(int value, int max, int percent) { if (percent >= 0) return value + ((max - value) * percent) / 100; return (value * (100 + percent)) / 100; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void BuildHudAnimTable(BYTE table[4][256], const int redPhase[4], const int greenPhase[4], const int bluePhase[4], int kind, int max) { int i, p; int red, green, blue, brightness; int useColor; for (i = 0; i < 256; i++) { red = sgLoad[i].peRed; green = sgLoad[i].peGreen; blue = sgLoad[i].peBlue; brightness = (red * 30 + green * 59 + blue * 11) / 100; useColor = FALSE; if (kind == 0) useColor = IsHudHealthColor(red, green, blue, brightness, max); else if (kind == 1) useColor = IsHudManaColor(red, green, blue, brightness, max); else useColor = IsHudRejuvColor(red, green, blue, brightness, max); for (p = 0; p < 4; p++) { if (!useColor) { table[p][i] = (BYTE)i; continue; } table[p][i] = FindNearestPaletteColor( PalClamp(HudShiftChannel(red, max, redPhase[p]), max), PalClamp(HudShiftChannel(green, max, greenPhase[p]), max), PalClamp(HudShiftChannel(blue, max, bluePhase[p]), max)); } } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void BuildHudAnimateTables() { int i, max; static const int sHealthOrbRed[4] = { 6, 16, 9, -4 }; static const int sHealthOrbGreen[4] = { 1, 4, 2, -2 }; static const int sHealthOrbBlue[4] = { -4, -10, -6, 0 }; static const int sManaOrbRed[4] = { -4, -10, -6, 0 }; static const int sManaOrbGreen[4] = { 2, 7, 4, -2 }; static const int sManaOrbBlue[4] = { 7, 18, 10, -4 }; static const int sHealthPotionRed[4] = { 3, 8, 5, -2 }; static const int sHealthPotionGreen[4] = { 0, 2, 1, -1 }; static const int sHealthPotionBlue[4] = { -2, -5, -3, 0 }; static const int sManaPotionRed[4] = { -2, -5, -3, 0 }; static const int sManaPotionGreen[4] = { 1, 4, 2, -1 }; static const int sManaPotionBlue[4] = { 4, 11, 6, -2 }; static const int sRejuvPotionRed[4] = { 4, 11, 6, -2 }; static const int sRejuvPotionGreen[4] = { -1, 1, 0, -1 }; static const int sRejuvPotionBlue[4] = { 4, 11, 6, -2 }; max = 63; for (i = 0; i < 256; i++) { if (sgLoad[i].peRed > 63 || sgLoad[i].peGreen > 63 || sgLoad[i].peBlue > 63) { max = 255; break; } } BuildHudAnimTable(gbHudHealthOrbTable, sHealthOrbRed, sHealthOrbGreen, sHealthOrbBlue, 0, max); BuildHudAnimTable(gbHudManaOrbTable, sManaOrbRed, sManaOrbGreen, sManaOrbBlue, 1, max); BuildHudAnimTable(gbHudPotionHealthTable, sHealthPotionRed, sHealthPotionGreen, sHealthPotionBlue, 0, max); BuildHudAnimTable(gbHudPotionManaTable, sManaPotionRed, sManaPotionGreen, sManaPotionBlue, 1, max); BuildHudAnimTable(gbHudPotionRejuvTable, sRejuvPotionRed, sRejuvPotionGreen, sRejuvPotionBlue, 2, max); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static int IsWorldGoldColor(int red, int green, int blue, int brightness, int max) { if (brightness < max / 8) return FALSE; if (red < green - max / 5) return FALSE; if (green < blue + max / 24) return FALSE; if (red < blue + max / 12) return FALSE; return TRUE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void BuildWorldGoldShimmerTables() { int i, p, max; int red, green, blue, brightness; static const int sGoldRed[4] = { 2, 22, 8, -8 }; static const int sGoldGreen[4] = { 1, 18, 6, -7 }; static const int sGoldBlue[4] = { -3, -16, -7, -4 }; max = 63; for (i = 0; i < 256; i++) { if (sgLoad[i].peRed > 63 || sgLoad[i].peGreen > 63 || sgLoad[i].peBlue > 63) { max = 255; break; } } for (i = 0; i < 256; i++) { red = sgLoad[i].peRed; green = sgLoad[i].peGreen; blue = sgLoad[i].peBlue; brightness = (red * 30 + green * 59 + blue * 11) / 100; for (p = 0; p < 4; p++) { if (!IsWorldGoldColor(red, green, blue, brightness, max)) { gbWorldGoldShimmerTable[p][i] = (BYTE)i; continue; } gbWorldGoldShimmerTable[p][i] = FindNearestPaletteColor( PalClamp(HudShiftChannel(red, max, sGoldRed[p]), max), PalClamp(HudShiftChannel(green, max, sGoldGreen[p]), max), PalClamp(HudShiftChannel(blue, max, sGoldBlue[p]), max)); } } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void SetPaletteEntries() { if (! lpDDPal) return; int nStart; int nColors; if (! fullscreen) { nStart = sgnStaticColors2; nColors = 256 - sgnStaticColors2*2; } else { nStart = 0; nColors = 256; } // HRESULT ddrval = lpDDPal->SetEntries(0,nStart,nColors,&sgCurr[nStart]); // ddraw_assert(ddrval); SDrawUpdatePalette(nStart,nColors,&sgCurr[nStart]); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void GammaPalette(PALETTEENTRY * pDst, const PALETTEENTRY * pSrc, int nNum) { double gamma = sglGamma / 100.0; for(int i = 0; i < nNum; i++,pDst++,pSrc++) { pDst->peRed = (BYTE)(256.0*pow(((double)pSrc->peRed)/256.0, gamma)); pDst->peGreen = (BYTE)(256.0*pow(((double)pSrc->peGreen)/256.0, gamma)); pDst->peBlue = (BYTE)(256.0*pow(((double)pSrc->peBlue)/256.0, gamma)); } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void SavePaletteSettings() { SRegSaveValue(gszProgKey,sgszGamma,0,sglGamma); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void GetPaletteSettings() { DWORD dwTemp = (DWORD) sglGamma; if (! SRegLoadValue(gszProgKey,sgszGamma,0,&dwTemp)) dwTemp = lGAMMA_MAX; sglGamma = (LONG) dwTemp; if (sglGamma < lGAMMA_MIN) sglGamma = lGAMMA_MIN; else if (sglGamma > lGAMMA_MAX) sglGamma = lGAMMA_MAX; sglGamma -= sglGamma % lGAMMA_STEP; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void FixWindowsPal() { int i; // reserve all colors so no mapping occurs for (i = 0; i < 256; i++) sgCurr[i].peFlags = PC_NOCOLLAPSE | PC_RESERVED; if (fullscreen) return; // get static color count HDC hDC = GetDC(NULL); sgnStaticColors2 = GetDeviceCaps(hDC, NUMRESERVED) / 2; // get the lower windows color set GetSystemPaletteEntries(hDC, 0, sgnStaticColors2, &sgCurr[0]); for (i = 0; i < sgnStaticColors2; i++) sgCurr[i].peFlags = 0; // get the upper windows color set i = 256 - sgnStaticColors2; GetSystemPaletteEntries(hDC, i, sgnStaticColors2, &sgCurr[i]); for ( ; i < 256; i++) sgCurr[i].peFlags = 0; ReleaseDC(NULL, hDC); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void CreatePalette() { GetPaletteSettings(); CopyMemory(sgCurr,sgLoad,sizeof(sgCurr)); FixWindowsPal(); HRESULT ddrval = lpDD->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE,sgCurr,&lpDDPal,NULL); if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_PAL_ERR,ddrval,__FILE__,__LINE__); ddrval = lpDDSPrimary->SetPalette(lpDDPal); if (ddrval != DD_OK) ErrorDlg(IDD_DDRAW_PAL_ERR,ddrval,__FILE__,__LINE__); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void LoadPalette(const char * pszFileName) { struct RGB { BYTE red; BYTE green; BYTE blue; } pal[256]; HSFILE hFile; app_assert(pszFileName); patSFileOpenFile(pszFileName,&hFile); patSFileReadFile(hFile,&pal[0],sizeof(pal)); patSFileCloseFile(hFile); for (int i = 0; i < 256; i++) { sgLoad[i].peRed = pal[i].red; sgLoad[i].peGreen = pal[i].green; sgLoad[i].peBlue = pal[i].blue; sgLoad[i].peFlags = 0; } // GammaPalette(sgBase, sgLoad, 256); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void LoadRndLvlPal(int l) { if (l == 0) { LoadPalette("Levels\\TownData\\Town.pal"); } else { char filestr[MAX_PATH]; int palnum = random(0, 4) + 1; sprintf(filestr, "Levels\\L%iData\\L%i_%i.PAL", l, l, palnum); // JKE add our palettes here if (l == 5) sprintf(filestr, "NLevels\\L5Data\\L5Base.PAL"); if (l == 6) { if (!gbOurNest) ++palnum; sprintf(filestr, "NLevels\\L%iData\\L%iBase%i.PAL", l, l, palnum); } LoadPalette(filestr); } BuildLevelTileEnhanceTables(); BuildTownWarmFlickerTables(); BuildHudAnimateTables(); BuildWorldGoldShimmerTables(); gbLevelTileEnhanceActive = TRUE; gbTownWarmFlickerActive = (l == 0); gbHudAnimateActive = FALSE; gbWorldGoldShimmerActive = TRUE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void ResetPal() { if (lpDDSPrimary && lpDDSPrimary->IsLost() == DDERR_SURFACELOST) if (DD_OK != lpDDSPrimary->Restore()) return; SDrawRealizePalette(); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void GammaUp() { if(sglGamma < lGAMMA_MAX) { sglGamma += lGAMMA_STEP; if (sglGamma > lGAMMA_MAX) sglGamma = lGAMMA_MAX; GammaPalette(sgCurr,sgBase,256); SetPaletteEntries(); } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void GammaDown() { if(sglGamma > lGAMMA_MIN) { sglGamma -= lGAMMA_STEP; if (sglGamma < lGAMMA_MIN) sglGamma = lGAMMA_MIN; GammaPalette(sgCurr,sgBase,256); SetPaletteEntries(); } } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ LONG GammaLevel(LONG lGamma) { if (lGamma != lGAMMA_READ) { // invert gamma hi/lo sglGamma = lGAMMA_MAX - lGamma + lGAMMA_MIN; GammaPalette(sgCurr,sgBase,256); SetPaletteEntries(); } // invert gamma hi/lo return lGAMMA_MAX - sglGamma + lGAMMA_MIN; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void SetFadeLevel(int fadeval) { if (! lpDD) return; for (int i = 0; i < 255; i++) { DWORD pv; pv = sgBase[i].peRed * fadeval; sgCurr[i].peRed = (BYTE) (pv/256); pv = sgBase[i].peGreen * fadeval; sgCurr[i].peGreen = (BYTE) (pv/256); pv = sgBase[i].peBlue * fadeval; sgCurr[i].peBlue = (BYTE) (pv/256); } // sgCurr[i].peRed = 0xff; // sgCurr[i].peGreen = 0xff; // sgCurr[i].peBlue = 0xff; Sleep(3); lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,NULL); SetPaletteEntries(); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void BlackPalette() { SetFadeLevel(0); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void PaletteFadeIn(int faderate) { GammaPalette(sgBase,sgLoad,256); for (int i = 0; i < 256; i += faderate) SetFadeLevel(i); SetFadeLevel(256); // un-gamma-fy base palette CopyMemory(sgBase,sgLoad,sizeof(sgBase)); sgbFadedIn = TRUE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void PaletteFadeOut(int faderate) { if (! sgbFadedIn) return; for (int i = 256; i > 0; i -= faderate) SetFadeLevel(i); SetFadeLevel(0); sgbFadedIn = FALSE; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void LavaCycle() { PALETTEENTRY temp = sgCurr[1]; for (int i = 1; i < 31; i++) { sgCurr[i].peRed = sgCurr[i + 1].peRed; sgCurr[i].peGreen = sgCurr[i + 1].peGreen; sgCurr[i].peBlue = sgCurr[i + 1].peBlue; // don't copy flags } sgCurr[i].peRed = temp.peRed; sgCurr[i].peGreen = temp.peGreen; sgCurr[i].peBlue = temp.peBlue; // don't copy flags SetPaletteEntries(); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ // JKE new cycle to do twin effects void TwinCycleCrypt() { int i; static int toggle = 0; static int toggle2 = 0; PALETTEENTRY temp; if (toggle2 > 1) { temp = sgCurr[15]; for (i = 15; i > 1; --i) { sgCurr[i].peRed = sgCurr[i - 1].peRed; sgCurr[i].peGreen = sgCurr[i - 1].peGreen; sgCurr[i].peBlue = sgCurr[i - 1].peBlue; // don't copy flags } sgCurr[i].peRed = temp.peRed; sgCurr[i].peGreen = temp.peGreen; sgCurr[i].peBlue = temp.peBlue; // don't copy flags toggle2 = 0; } else ++toggle2; if (toggle > 0) { temp = sgCurr[31]; for (i = 31; i > 16; --i) { sgCurr[i].peRed = sgCurr[i - 1].peRed; sgCurr[i].peGreen = sgCurr[i - 1].peGreen; sgCurr[i].peBlue = sgCurr[i - 1].peBlue; } sgCurr[i].peRed = temp.peRed; sgCurr[i].peGreen = temp.peGreen; sgCurr[i].peBlue = temp.peBlue; SetPaletteEntries(); ++toggle; } else toggle = 1; } void TwinCycleNest() { int i; static int toggle = 0; static int toggle2 = 0; PALETTEENTRY temp; if (toggle2 == 2) { temp = sgCurr[8]; for (i = 8; i > 1; --i) { sgCurr[i].peRed = sgCurr[i - 1].peRed; sgCurr[i].peGreen = sgCurr[i - 1].peGreen; sgCurr[i].peBlue = sgCurr[i - 1].peBlue; // don't copy flags } sgCurr[i].peRed = temp.peRed; sgCurr[i].peGreen = temp.peGreen; sgCurr[i].peBlue = temp.peBlue; // don't copy flags toggle2 = 0; } else ++toggle2; if (toggle == 2) { temp = sgCurr[15]; for (i = 15; i > 9; --i) { sgCurr[i].peRed = sgCurr[i - 1].peRed; sgCurr[i].peGreen = sgCurr[i - 1].peGreen; sgCurr[i].peBlue = sgCurr[i - 1].peBlue; } sgCurr[i].peRed = temp.peRed; sgCurr[i].peGreen = temp.peGreen; sgCurr[i].peBlue = temp.peBlue; SetPaletteEntries(); toggle = 0; } else ++toggle; } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void UpdateLavaPalette() { for (int i = 0; i < 32; i++) sgBase[i] = sgLoad[i]; GammaPalette(sgCurr,sgBase,32); SetPaletteEntries(); } /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ void MeshLavaPalette(int fadeval) { int i; for (i = 32 - fadeval; i >= 0; i--) sgBase[i] = sgLoad[i]; GammaPalette(sgCurr, sgBase, 32); SetPaletteEntries(); }