#include #include #include #include #include #include "typedefs.h" #include "misc.h" #include "globals.h" #include "textio.h" #include "palette.h" #include "debug4g.h" #include "resource.h" #include "error.h" #include "screen.h" #include "helix.h" #include "trig.h" #include "gfx.h" typedef uchar GAMMA_SUBTABLE[256]; static GAMMA_SUBTABLE *gammaTable; static RGB baseDAC[256], curDAC[256], fromDAC[256], toRGB; static RGB *palTable[kMaxPalettes]; static int effectR = 0, effectG = 0, effectB = 0; static BOOL DacInvalid = TRUE; static long messageTime = 0; static char message[256]; static int curPalette = kPalNormal; static int curGamma = 0; static RGB StdPal[32] = { { 0, 0, 0}, { 0, 0,170}, { 0,170, 0}, { 0,170,170}, {170, 0, 0}, {170, 0,170}, {170, 85, 0}, {170,170,170}, { 85, 85, 85}, { 85, 85,255}, { 85,255, 85}, { 85,255,255}, {255, 85, 85}, {255, 85,255}, {255,255, 85}, {255,255,255}, {241,241,241}, {226,226,226}, {211,211,211}, {196,196,196}, {181,181,181}, {166,166,166}, {151,151,151}, {136,136,136}, {120,120,120}, {105,105,105}, { 90, 90, 90}, { 75, 75, 75}, { 60, 60, 60}, { 45, 45, 45}, { 30, 30, 30}, { 15, 15, 15}, }; struct LOADITEM { int index; char *name; }; static LOADITEM PLU[] = { { kPLUNormal, "NORMAL" }, { kPLUFlame, "FLAME" }, { kPLUCold, "COLD" }, { kPLURed, "BEAST" }, { kPLUGray, "GRAY" }, { kPLUGrayish, "GRAYISH" }, { kPLUCultist2, "TOMMY" }, { kPLUSpider1, "SPIDER1" }, { kPLUSpider2, "SPIDER2" }, { kPLUSpider3, "SPIDER3" }, { kPLUPlayer1, "P0" }, // also kPLUPlayer5 { kPLUPlayer2, "P1" }, // also kPLUPlayer6 { kPLUPlayer3, "P2" }, // also kPLUPlayer7 { kPLUPlayer4, "P3" }, // also kPLUPlayer8 }; static LOADITEM PAL[] = { { kPalNormal, "BLOOD" }, { kPalWater, "WATER" }, { kPalBeast, "BEAST" }, }; // exported variables int gGammaLevels; BOOL gFogMode = FALSE; BYTE gStdColor[32]; // standard 32 colors // Weight coefficients for color matching #define kWeightR 1 #define kWeightG 1 #define kWeightB 1 BYTE scrFindClosestColor( int r, int g, int b ) { int i; int dr, dg, db, dist, matchDist, match; matchDist = 0x7FFFFFFF; for ( i = 0; i < 256; i++ ) { dist = 0; dg = (int)palette[i].g - g; dist += kWeightG * dg * dg; if ( dist >= matchDist ) continue; dr = (int)palette[i].r - r; dist += kWeightR * dr * dr; if ( dist >= matchDist ) continue; db = (int)palette[i].b - b; dist += kWeightB * db * db; if ( dist >= matchDist ) continue; matchDist = dist; match = i; if (dist == 0) break; } return (BYTE)match; } void scrCreateStdColors( void ) { for (int i = 0; i < LENGTH(StdPal); i++) gStdColor[i] = scrFindClosestColor(StdPal[i].r, StdPal[i].g, StdPal[i].b); } void scrLoadPLUs( void ) { int i; if ( gFogMode ) { RESHANDLE hRemap; hRemap = gSysRes.Lookup("FOG", ".FLU"); if (hRemap == NULL) ThrowError("FOG.FLU not found", ES_ERROR); palookup[0] = (BYTE *)gSysRes.Lock(hRemap); for ( i = 0; i < LENGTH(PLU); i++ ) { palookup[PLU[i].index] = (BYTE *)palookup[0]; } parallaxvisibility = 8192; } else { for ( i = 0; i < LENGTH(PLU); i++ ) { RESHANDLE hRemap; hRemap = gSysRes.Lookup(PLU[i].name, ".plu"); if (hRemap == NULL) { char buffer[128]; sprintf(buffer, "%s.PLU not found", PLU[i].name); ThrowError(buffer, ES_ERROR); } if ( gSysRes.Size(hRemap) / 256 != kPalLookups ) ThrowError("Incorrect PLU size", ES_ERROR); palookup[PLU[i].index] = (uchar *)gSysRes.Lock(hRemap); } } } void scrLoadPalette() { int i; tioPrint("Loading palettes"); for ( i = 0; i < LENGTH(PAL); i++ ) { RESHANDLE hRemap; hRemap = gSysRes.Lookup(PAL[i].name, ".pal"); if (hRemap == NULL) { char buffer[128]; sprintf(buffer, "%s.PAL not found", PAL[i].name); ThrowError(buffer, ES_ERROR); } palTable[PAL[i].index] = (RGB *)gSysRes.Lock(hRemap); } // copy the default palette into ken's variable so Std color stuff still works memcpy(palette, palTable[kPalNormal], sizeof(palette)); paletteloaded = 1; numpalookups = kPalLookups; scrLoadPLUs(); RESHANDLE hTransluc; tioPrint("Loading translucency table"); hTransluc = gSysRes.Lookup("trans", ".tlu"); if (hTransluc == NULL) ThrowError("TRANS.TLU not found", ES_ERROR); transluc = (uchar *)gSysRes.Lock(hTransluc); fixtransluscence(transluc); } void scrSetMessage(char *s) { messageTime = gFrameClock; strcpy(message, s); } void scrDisplayMessage( int nColor ) { if (gFrameClock < messageTime + kTimerRate * 2) gfxDrawText(windowx1, windowy1, nColor, message, 0); } void scrSetPalette( int nPalette ) { curPalette = nPalette; scrSetGamma(curGamma); // reset baseline colors } void scrSetGamma( int nGamma ) { int i; dassert(nGamma < gGammaLevels); curGamma = nGamma; for ( i = 0; i < 256; i++ ) { baseDAC[i].r = (uchar)(gammaTable[nGamma][palTable[curPalette][i].r]); baseDAC[i].g = (uchar)(gammaTable[nGamma][palTable[curPalette][i].g]); baseDAC[i].b = (uchar)(gammaTable[nGamma][palTable[curPalette][i].b]); } // force a DAC update DacInvalid = TRUE; } void scrDacRelEffect( int r, int g, int b ) { effectR = ClipHigh(effectR + r, 384); effectG = ClipHigh(effectG + g, 384); effectB = ClipHigh(effectB + b, 384); // effectR += r; // effectG += g; // effectB += b; DacInvalid = TRUE; } void scrDacAbsEffect( int r, int g, int b ) { effectR = r; effectG = g; effectB = b; DacInvalid = TRUE; } void scrSetupFade( BYTE r, BYTE g, BYTE b ) { memcpy(fromDAC, curDAC, sizeof(fromDAC)); toRGB.r = r; toRGB.g = g; toRGB.b = b; } void scrSetupUnfade( void ) { memcpy(fromDAC, baseDAC, sizeof(fromDAC)); } void scrFadeAmount( int nFrac ) { for ( int i = 0; i < 256; i++ ) { curDAC[i].r = (BYTE)dmulscale16(0x10000 - nFrac, fromDAC[i].r, nFrac, toRGB.r); curDAC[i].g = (BYTE)dmulscale16(0x10000 - nFrac, fromDAC[i].g, nFrac, toRGB.g); curDAC[i].b = (BYTE)dmulscale16(0x10000 - nFrac, fromDAC[i].b, nFrac, toRGB.b); } gSetDACRange(0, 256, curDAC); } void scrSetDac( ulong nTicks ) { int i; // don't set the palette in stereo red/blue mode if ( vidoption == 6 ) return; // don't update DACs if no effect necessary if ( DacInvalid ) { for (i = 0; i < 256; i++) { curDAC[i].r = (uchar)ClipRange(baseDAC[i].r + effectR, 0, 255); curDAC[i].g = (uchar)ClipRange(baseDAC[i].g + effectG, 0, 255); curDAC[i].b = (uchar)ClipRange(baseDAC[i].b + effectB, 0, 255); } gSetDACRange(0, 256, curDAC); } DacInvalid = FALSE; if ( effectR | effectG | effectB ) { DacInvalid = TRUE; if (effectR > 0) effectR = ClipLow(effectR - nTicks, 0); else if (effectR < 0) effectR = ClipHigh(effectR + nTicks, 0); if (effectG > 0) effectG = ClipLow(effectG - nTicks, 0); else if (effectG < 0) effectG = ClipHigh(effectG + nTicks, 0); if (effectB > 0) effectB = ClipLow(effectB - nTicks, 0); else if (effectB < 0) effectB = ClipHigh(effectB + nTicks, 0); } } void scrInit( void ) { RESHANDLE hRes; curPalette = kPalNormal; curGamma = 0; tioPrint("Loading gamma correction table"); hRes = gSysRes.Lookup("gamma", ".dat"); if ( hRes == NULL ) ThrowError("Gamma table not found", ES_ERROR); gGammaLevels = gSysRes.Size(hRes) / 256; gammaTable = (GAMMA_SUBTABLE *)gSysRes.Lock(hRes); } void scrSetGameMode( void ) { setgamemode(); // initialize y lookups for helix driver for (int i = 0; i < kMaxRows; i++) gYLookup[i] = ylookup[i]; if ( vidoption == 1 || vidoption == 2 ) { gPageTable[0].bytesPerRow = ylookup[1]; gPageTable[0].begin = (unsigned)frameplace; } clearview(0); scrNextPage(); scrSetDac(0); } void scrNextPage( void ) { nextpage(); switch ( vidoption ) { case 0: // non-chained if (chainnumpages > 1) gPageTable[0].begin = (unsigned)chainplace; break; case 1: // VESA 2.0 linear buffer gPageTable[0].begin = (unsigned)frameplace; case 2: // memory buffered VESA/13h break; case 3: // Tseng ET4000 break; case 4: // Paradise break; case 5: // S3 break; case 6: // Crystal Eyes break; case 7: // Red/Blue Stereogram break; } }