palette.cc

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2000-2001  The Exult Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #ifdef HAVE_CONFIG_H
00020 #  include <config.h>
00021 #endif
00022 
00023 #ifndef ALPHA_LINUX_CXX
00024 #  include <cstring> 
00025 #endif
00026 #include "files/U7file.h" 
00027 #include "palette.h"
00028 #include "ibuf8.h"
00029 #include "utils.h"
00030 #include "fnames.h"
00031 #include "gamewin.h"
00032 
00033 #include "SDL_timer.h"
00034 
00035 #ifndef UNDER_CE
00036 using std::memcpy;
00037 using std::memset;
00038 using std::size_t;
00039 using std::string;
00040 #endif
00041 
00042 Palette::Palette()
00043   : win(Game_window::get_instance()->get_win()), 
00044       palette(-1), brightness(100), 
00045       faded_out(false), fades_enabled(true), max_val(63)
00046       {
00047   }
00048 
00049 Palette::~Palette()
00050   {
00051   }
00052   
00053 /*
00054  *  Fade the current palette in or out.
00055  *  Note:  If pal_num != -1, the current palette is set to it.
00056  */
00057 
00058 void Palette::fade
00059   (
00060   int cycles,     // Length of fade.
00061   int inout,      // 1 to fade in, 0 to fade to black.
00062   int pal_num     // 0-11, or -1 for current.
00063   )
00064   {
00065     if (pal_num == -1) pal_num = palette;
00066     load(PALETTES_FLX, pal_num);
00067     if(inout)
00068     fade_in(cycles);
00069     else
00070     fade_out(cycles);
00071     faded_out = !inout;   // Be sure to set flag.
00072   }
00073 
00074 /*
00075  *  Flash the current palette red.
00076  */
00077 
00078 void Palette::flash_red
00079   (
00080   )
00081   {
00082   int savepal = palette;
00083   set(PALETTE_RED);   // Palette 8 is the red one.
00084   win->show();
00085   SDL_Delay(100);
00086   set(savepal);
00087   Game_window::get_instance()->set_painted();
00088   }
00089 
00090 /*
00091  *  Read in a palette.
00092  */
00093 
00094 void Palette::set
00095   (
00096   int pal_num,      // 0-11, or -1 to leave unchanged.
00097   int new_brightness,   // New percentage, or -1.
00098   bool repaint
00099   )
00100   {
00101   if ((palette == pal_num || pal_num == -1) &&
00102     (brightness == new_brightness || new_brightness == -1))
00103     return;     // Already set.
00104   if (pal_num != -1)
00105     palette = pal_num;  // Store #.
00106   if (new_brightness > 0)
00107     brightness = new_brightness;
00108   if (faded_out)
00109     return;     // In the black.
00110   
00111   load(PALETTES_FLX, palette);  // could throw!
00112   set_brightness(brightness);
00113   apply(repaint);
00114   }
00115 
00116 void Palette::apply(bool repaint)
00117 {
00118   win->set_palette(pal1, max_val, brightness);
00119   if (repaint)
00120     win->show();
00121 }
00122 
00123 /*
00124  *  Returns 0 if file not found.
00125  */
00126 void Palette::load(const char *fname, int index, const char *xfname, int xindex)
00127   {
00128   size_t len;
00129   char *buf = 0;
00130   if (std::strncmp(fname, "<STATIC>/", sizeof("<STATIC>/") - 1) == 0 &&
00131           is_system_path_defined("<PATCH>"))
00132     {     // Check in "patch" dir. first.
00133     string pname("<PATCH>/");
00134     pname += fname + sizeof("<STATIC>/") - 1;
00135     U7object pal(pname.c_str(), index);
00136     try {
00137       buf = pal.retrieve(len);
00138     }
00139     catch (exult_exception& e) {
00140       buf = 0;
00141     }
00142     }
00143   if (!buf)     // Not in patch.
00144     {
00145     U7object pal(fname, index);
00146     buf = pal.retrieve(len);// this may throw an exception
00147     }
00148   if(len==768) {  // Simple palette
00149     if (xindex >= 0) {  // Get xform table.
00150       U7object xform(xfname, xindex);
00151       unsigned char *xbuf = 0;
00152       size_t xlen;
00153       try {
00154 #if 0 /* +++++TESTING */
00155         xbuf = new unsigned char[256];
00156         Game_window *gwin = 
00157           Game_window::get_instance();
00158         memcpy(xbuf, gwin->get_xform(11 - xindex - 1),
00159                   256);
00160 #else
00161         xbuf = (unsigned char *) xform.retrieve( xlen);
00162 #endif
00163         for (int i = 0; i < 256; i++) {
00164           int ix = xbuf[i];
00165           pal1[3*i] = buf[3*ix];
00166           pal1[3*i+1] = buf[3*ix+1];
00167           pal1[3*i+2] = buf[3*ix+2];
00168         }
00169       }
00170       catch( const std::exception & err ) {
00171         xindex = -1;
00172       }
00173       delete [] xbuf;
00174     }
00175     if (xindex < 0)   // Set the first palette
00176       memcpy(pal1,buf,768);
00177     memset(pal2,0,768); // The second one is black
00178   } else {      // Double palette
00179     for(int i=0; i<768; i++) {
00180       pal1[i]=buf[i*2];
00181       pal2[i]=buf[i*2+1];
00182     }
00183   }
00184   delete [] buf;
00185   }
00186 /*void Palette::load(const char *fname, int index, const char *xfname, int xindex)
00187   {
00188   U7object pal(fname, index);
00189   size_t len;
00190   char *buf;
00191   pal.retrieve(&buf, len);  // this may throw an exception
00192   if(len==768) {  // Simple palette
00193     if (xindex >= 0)  // Get xform table.
00194       {
00195       U7object xform(xfname, xindex);
00196       unsigned char *xbuf; size_t xlen;
00197       if (!xform.retrieve(&xbuf, xlen))
00198         xindex = -1;
00199       else
00200         for (int i = 0; i < 256; i++)
00201           {
00202           int ix = xbuf[i];
00203           pal1[3*i] = buf[3*ix];
00204           pal1[3*i+1] = buf[3*ix+1];
00205           pal1[3*i+2] = buf[3*ix+2];
00206           }
00207       delete [] xbuf;
00208       }
00209     if (xindex < 0)   // Set the first palette
00210       memcpy(pal1,buf,768);
00211     memset(pal2,0,768); // The second one is black
00212   } else {      // Double palette
00213     for(int i=0; i<768; i++) {
00214       pal1[i]=buf[i*2];
00215       pal2[i]=buf[i*2+1];
00216     }
00217   }
00218   delete [] buf;
00219   }
00220 */
00221   
00222 void Palette::set_brightness(int bright)
00223   {
00224     brightness = bright;
00225   }
00226   
00227 void Palette::fade_in(int cycles)
00228 {
00229   if (fades_enabled)
00230   {
00231     unsigned char fade_pal[768];
00232     unsigned int ticks = SDL_GetTicks() + 20;
00233     for (int i = 0; i <= cycles; i++)
00234     {
00235       for(int c=0; c < 768; c++)
00236         fade_pal[c] = ((pal1[c]-pal2[c])*i)/cycles+pal2[c];
00237       win->set_palette(fade_pal, max_val, brightness);
00238       // Frame skipping on slow systems
00239       if (i == cycles || ticks >= SDL_GetTicks() ||
00240           !Game_window::get_instance()->get_frame_skipping())
00241         win->show();
00242       while (ticks >= SDL_GetTicks())
00243         ;
00244       ticks += 20;
00245     }
00246   }
00247   else
00248   {
00249     win->set_palette(pal1, max_val, brightness);
00250     win->show();
00251   }
00252 }
00253 
00254 void Palette::fade_out(int cycles)
00255 {
00256   if (fades_enabled)
00257   {
00258     unsigned char fade_pal[768];
00259     unsigned int ticks = SDL_GetTicks() + 20;
00260     for (int i = cycles; i >= 0; i--)
00261     {
00262       for(int c=0; c < 768; c++)
00263         fade_pal[c] = ((pal1[c]-pal2[c])*i)/cycles+pal2[c];
00264       win->set_palette(fade_pal, max_val, brightness);
00265       // Frame skipping on slow systems
00266       if (i == 0 || ticks >= SDL_GetTicks() ||
00267          !Game_window::get_instance()->get_frame_skipping())
00268         win->show();
00269       while (ticks >= SDL_GetTicks())
00270         ;
00271       ticks += 20;
00272     }
00273   }
00274   else
00275   {
00276     win->set_palette(pal2, max_val, brightness);
00277     win->show();
00278   }
00279 //Messes up sleep.          win->set_palette(pal1, max_val, brightness);
00280 }
00281 
00282 //  Find index (0-255) of closest color (r,g,b < 64).
00283 int Palette::find_color(int r, int g, int b) {
00284   int best_index = -1;
00285   long best_distance = 0xfffffff;
00286           // But don't search rotating colors.
00287   for (int i = 0; i < 0xe0; i++) {
00288           // Get deltas.
00289     long dr = r - pal1[3*i], dg = g - pal1[3*i + 1], 
00290               db = b - pal1[3*i + 2];
00291           // Figure distance-squared.
00292     long dist = dr*dr + dg*dg + db*db;
00293     if (dist < best_distance) { // Better than prev?
00294       best_index = i;
00295       best_distance = dist;
00296     }
00297   }
00298   return best_index;
00299 }
00300 
00301 /*
00302  *  Create a translucency table for this palette seen through a given
00303  *  color.  (Based on a www.gamedev.net article by Jesse Towner.)
00304  */
00305 
00306 void Palette::create_trans_table
00307   (
00308           // Color to blend with:
00309   unsigned char br, unsigned bg, unsigned bb,
00310   int alpha,      // 0-255, applied to 'blend' color.
00311   unsigned char *table    // 256 indices are stored here.
00312   )
00313   {
00314   for (int i = 0; i < 256; i++)
00315     {
00316     int newr = ((int) br * alpha)/255 + 
00317         ((int) pal1[i*3] * (255 - alpha))/255;
00318     int newg = ((int) bg * alpha)/255 + 
00319         ((int) pal1[i*3 + 1] * (255 - alpha))/255;
00320     int newb = ((int) bb * alpha)/255 + 
00321         ((int) pal1[i*3 + 2] * (255 - alpha))/255;
00322     table[i] = find_color(newr, newg, newb);
00323     }
00324   }
00325 
00326 void Palette::show() {
00327   for (int x = 0; x < 16; x++) {
00328     for (int y = 0; y < 16; y++) {
00329       win->fill8(y*16+x, 8, 8, x*8, y*8);
00330     }
00331   } 
00332 }
00333 
00334 void Palette::set_color(int nr, int r, int g, int b) {
00335   pal1[nr*3] = r;
00336   pal1[nr*3+1] = g;
00337   pal1[nr*3+2] = b;
00338 }
00339 
00340 void Palette::set_palette(unsigned char palnew[768]) {
00341   memcpy(pal1,palnew,768);
00342   memset(pal2,0,768);
00343 }
00344 
00345 void Palette::set_max_val(int max)
00346 {
00347   max_val = max;
00348 }
00349 
00350 int Palette::get_max_val()
00351 {
00352   return max_val;
00353 }

Generated on Mon Jul 9 14:42:49 2007 for ExultEngine by  doxygen 1.5.1